From da3b4aa8157303faea95b104da69113b0a452944 Mon Sep 17 00:00:00 2001 From: popomore Date: Wed, 23 Aug 2023 03:54:48 -0300 Subject: [PATCH] feat: first implement logger --- README.md | 2 +- core/logger/CHANGELOG.md | 1 + core/logger/README.md | 3 ++ core/logger/index.ts | 3 ++ core/logger/package.json | 54 +++++++++++++++++++ core/logger/src/decorator/LoggerDecorator.ts | 23 ++++++++ core/logger/src/logger/BaseLogger.ts | 35 ++++++++++++ core/logger/src/logger/LoggerFactory.ts | 43 +++++++++++++++ core/logger/src/logger/LoggerLevel.ts | 7 +++ core/logger/src/logger/LoggerUtil.ts | 27 ++++++++++ core/logger/src/module/Logger.ts | 10 ++++ core/logger/src/type/ILogger.ts | 7 +++ core/logger/src/type/LoggerDecoratorParams.ts | 17 ++++++ core/logger/test/Logger.test.ts | 43 +++++++++++++++ .../test/fixtures/logger/TraceLogger.ts | 6 +++ core/logger/tsconfig.json | 12 +++++ core/logger/tsconfig.pub.json | 12 +++++ 17 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 core/logger/CHANGELOG.md create mode 100644 core/logger/README.md create mode 100644 core/logger/index.ts create mode 100644 core/logger/package.json create mode 100644 core/logger/src/decorator/LoggerDecorator.ts create mode 100644 core/logger/src/logger/BaseLogger.ts create mode 100644 core/logger/src/logger/LoggerFactory.ts create mode 100644 core/logger/src/logger/LoggerLevel.ts create mode 100644 core/logger/src/logger/LoggerUtil.ts create mode 100644 core/logger/src/module/Logger.ts create mode 100644 core/logger/src/type/ILogger.ts create mode 100644 core/logger/src/type/LoggerDecoratorParams.ts create mode 100644 core/logger/test/Logger.test.ts create mode 100644 core/logger/test/fixtures/logger/TraceLogger.ts create mode 100644 core/logger/tsconfig.json create mode 100644 core/logger/tsconfig.pub.json diff --git a/README.md b/README.md index be86fb99..2d566395 100644 --- a/README.md +++ b/README.md @@ -762,7 +762,7 @@ import { EggObjectFactory } from '@eggjs/tegg'; export class HelloService { @Inject() private readonly eggObjectFactory: EggObjectFactory; - + async hello(): Promise { const helloImpl = await this.eggObjectFactory.getEggObject(AbstractHello, HelloType.BAR); return helloImpl.hello(); diff --git a/core/logger/CHANGELOG.md b/core/logger/CHANGELOG.md new file mode 100644 index 00000000..420e6f23 --- /dev/null +++ b/core/logger/CHANGELOG.md @@ -0,0 +1 @@ +# Change Log diff --git a/core/logger/README.md b/core/logger/README.md new file mode 100644 index 00000000..9df0f6d9 --- /dev/null +++ b/core/logger/README.md @@ -0,0 +1,3 @@ +# `@eggjs/logger-decorator` + +# Usage diff --git a/core/logger/index.ts b/core/logger/index.ts new file mode 100644 index 00000000..ab249793 --- /dev/null +++ b/core/logger/index.ts @@ -0,0 +1,3 @@ +export * from './src/decorator/LoggerDecorator'; +export * from './src/logger/BaseLogger'; +export * from './src/logger/LoggerLevel'; diff --git a/core/logger/package.json b/core/logger/package.json new file mode 100644 index 00000000..1e54fc14 --- /dev/null +++ b/core/logger/package.json @@ -0,0 +1,54 @@ +{ + "name": "@eggjs/logger", + "version": "3.14.3", + "description": "tegg logger", + "keywords": [ + "tegg", + "logger", + "typescript", + "egg" + ], + "author": "popomore ", + "homepage": "https://github.com/eggjs/tegg", + "repository": { + "type": "git", + "url": "git@github.com:eggjs/tegg.git", + "directory": "core/logger" + }, + "dependencies": { + "@eggjs/core-decorator": "^3.14.3", + "@eggjs/tegg-common-util": "^3.14.3", + "@eggjs/tegg-metadata": "^3.14.3", + "is-type-of": "^2.0.1" + }, + "scripts": { + "test": "cross-env NODE_ENV=test NODE_OPTIONS='--no-deprecation' mocha", + "clean": "tsc -b --clean", + "tsc": "npm run clean && tsc -p ./tsconfig.json", + "tsc:pub": "npm run clean && tsc -p ./tsconfig.pub.json", + "prepublishOnly": "npm run tsc:pub" + }, + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=14.0.0" + }, + "license": "MIT", + "main": "dist/index.js", + "files": [ + "dist/**/*.js", + "dist/**/*.d.ts" + ], + "bugs": { + "url": "https://github.com/eggjs/tegg/issues" + }, + "devDependencies": { + "@types/mocha": "^10.0.1", + "@types/node": "^20.2.4", + "cross-env": "^7.0.3", + "mocha": "^10.2.0", + "ts-node": "^10.9.1", + "typescript": "^5.0.4" + } +} diff --git a/core/logger/src/decorator/LoggerDecorator.ts b/core/logger/src/decorator/LoggerDecorator.ts new file mode 100644 index 00000000..e75956c4 --- /dev/null +++ b/core/logger/src/decorator/LoggerDecorator.ts @@ -0,0 +1,23 @@ +import { AccessLevel, EggProtoImplClass, PrototypeUtil, SingletonProto } from '@eggjs/core-decorator'; +import { StackUtil } from '@eggjs/tegg-common-util'; +import { LoggerMetaUtil } from '../logger/LoggerUtil'; +import { ILogger } from '../type/ILogger'; +import { LoggerDecoratorParams } from '../type/LoggerDecoratorParams'; + +/** + * Logger Decorator + * + * Define the object is Logger object + */ +export function LoggerDecorator(params?: LoggerDecoratorParams) { + return function(constructor: EggProtoImplClass) { + LoggerMetaUtil.setLoggerFlag(constructor); + LoggerMetaUtil.setLoggerMeta(constructor, params); + const func = SingletonProto({ + accessLevel: AccessLevel.PRIVATE, + name: params?.name, + }); + func(constructor); + PrototypeUtil.setFilePath(constructor, StackUtil.getCalleeFromStack(false, 5)); + }; +} diff --git a/core/logger/src/logger/BaseLogger.ts b/core/logger/src/logger/BaseLogger.ts new file mode 100644 index 00000000..1d12a0cf --- /dev/null +++ b/core/logger/src/logger/BaseLogger.ts @@ -0,0 +1,35 @@ +import { Logger } from 'egg-logger'; +import { LoggerFactory } from './LoggerFactory'; +import { ILogger } from '../type/ILogger'; +import { LoggerMetaUtil } from './LoggerUtil'; + +export class BaseLogger implements ILogger { + + #logger: Logger; + + constructor() { + const options = LoggerMetaUtil.getLoggerMeta(this.constructor as any); + this.#logger = LoggerFactory.getOrCreateLogger(options); + } + + public debug(message: any, ...args: any[]): void { + this.#logger.debug(message, ...args); + } + + public error(message: any, ...args: any[]): void { + this.#logger.error(message, ...args); + } + + public info(message: any, ...args: any[]): void { + this.#logger.error(message, ...args); + } + + public warn(message: any, ...args: any[]): void { + this.#logger.warn(message, ...args); + } + + public write(message: any): void { + this.#logger.write(message); + } + +} diff --git a/core/logger/src/logger/LoggerFactory.ts b/core/logger/src/logger/LoggerFactory.ts new file mode 100644 index 00000000..1a7a0b1e --- /dev/null +++ b/core/logger/src/logger/LoggerFactory.ts @@ -0,0 +1,43 @@ +import { Logger } from 'egg-logger'; +import is from 'is-type-of'; +import { LoggerDecoratorParams } from '../type/LoggerDecoratorParams'; +import { LoggerLevel } from './LoggerLevel'; + +const defaultOptions: Partial = { + level: LoggerLevel.INFO, +}; + +export class LoggerFactory { + + static #loggerMap = new Map(); + + static getOrCreateLogger(options?: LoggerDecoratorParams): Logger { + const opt = { + ...defaultOptions, + ...options, + }; + + if (is.nullable(opt.file)) throw new Error('options.file is required'); + if (is.nullable(opt.name)) throw new Error('options.name is required'); + + const name = opt.name; + let logger = this.#loggerMap.get(name); + if (logger) return logger; + + logger = new Logger({ + level: opt.level, + file: opt.file, + }); + this.#loggerMap.set(name, logger); + return logger; + } + + static getLogger(name: string): Logger | undefined { + return this.#loggerMap.get(name); + } + + // static destroyAll() { + + // } + +} diff --git a/core/logger/src/logger/LoggerLevel.ts b/core/logger/src/logger/LoggerLevel.ts new file mode 100644 index 00000000..0f7805fb --- /dev/null +++ b/core/logger/src/logger/LoggerLevel.ts @@ -0,0 +1,7 @@ +export enum LoggerLevel { + DEBUG = 'DEBUG', + INFO = 'INFO', + WARN = 'WARN', + ERROR = 'ERROR', + NONE = 'NONE', +} diff --git a/core/logger/src/logger/LoggerUtil.ts b/core/logger/src/logger/LoggerUtil.ts new file mode 100644 index 00000000..a1b2f7ef --- /dev/null +++ b/core/logger/src/logger/LoggerUtil.ts @@ -0,0 +1,27 @@ +import { EggProtoImplClass, MetadataUtil } from '@eggjs/core-decorator'; +import { LoggerDecoratorParams } from '../type/LoggerDecoratorParams'; +import { ILogger } from '../type/ILogger'; +import is from 'is-type-of'; + +export const LOGGER_OPTIONS = Symbol.for('EggPrototype#loggerOptions'); +export const IS_LOGGER = Symbol.for('EggPrototype#isLogger'); + +export class LoggerMetaUtil { + static setLoggerMeta(clazz: EggProtoImplClass, params?: LoggerDecoratorParams) { + MetadataUtil.defineMetaData(LOGGER_OPTIONS, params, clazz); + } + + static getLoggerMeta(clazz: EggProtoImplClass): LoggerDecoratorParams | undefined { + return MetadataUtil.getOwnMetaData(LOGGER_OPTIONS, clazz); + } + + static setLoggerFlag(clazz: EggProtoImplClass) { + MetadataUtil.defineMetaData(IS_LOGGER, true, clazz); + } + + static getLoggerFlag(clazz: EggProtoImplClass): boolean { + const result = MetadataUtil.getOwnMetaData(IS_LOGGER, clazz); + return is.undefined(result) ? false : result; + } + +} diff --git a/core/logger/src/module/Logger.ts b/core/logger/src/module/Logger.ts new file mode 100644 index 00000000..7f8377e1 --- /dev/null +++ b/core/logger/src/module/Logger.ts @@ -0,0 +1,10 @@ +import { LoggerDecorator } from '../decorator/LoggerDecorator'; +import { BaseLogger } from '../logger/BaseLogger'; + +@LoggerDecorator({ + name: 'logger', + transports: [ + new (require('egg-logger').EggConsoleTransport)({ + ], +}) +export class Logger extends BaseLogger {} diff --git a/core/logger/src/type/ILogger.ts b/core/logger/src/type/ILogger.ts new file mode 100644 index 00000000..6e365f6d --- /dev/null +++ b/core/logger/src/type/ILogger.ts @@ -0,0 +1,7 @@ +export interface ILogger { + error(message: any, ...args: any[]): void; + warn(message: any, ...args: any[]): void; + info(message: any, ...args: any[]): void; + debug(message: any, ...args: any[]): void; + write(message: any, ...args: any[]): void; +} diff --git a/core/logger/src/type/LoggerDecoratorParams.ts b/core/logger/src/type/LoggerDecoratorParams.ts new file mode 100644 index 00000000..231847bb --- /dev/null +++ b/core/logger/src/type/LoggerDecoratorParams.ts @@ -0,0 +1,17 @@ +import { LoggerLevel } from '../logger/LoggerLevel'; + +export interface LoggerDecoratorParams { + name?: string; + level?: LoggerLevel; + file: string; + // encoding?: string; + // consoleLevel?: LoggerLevel; + // formatter?: (meta?: LoggerMeta) => string; + // paddingMessageFormatter?: (ctx: object) => string; + // jsonFile?: string; + // outputJSON?: boolean; + // buffer?: boolean; + // dateISOFormat?: boolean; + // eol?: string; + // concentrateError?: 'duplicate' | 'redirect' | 'ignore'; +} diff --git a/core/logger/test/Logger.test.ts b/core/logger/test/Logger.test.ts new file mode 100644 index 00000000..331a52d3 --- /dev/null +++ b/core/logger/test/Logger.test.ts @@ -0,0 +1,43 @@ +import path from 'path'; +import { LoadUnitInstance, LoadUnitInstanceFactory } from '@eggjs/tegg-runtime'; +import { LoadUnitFactory } from '@eggjs/tegg-metadata'; +import { EggTestContext } from '../../test-util'; +import { HelloService } from './fixtures/modules/dynamic-inject-module/HelloService'; +import { CoreTestHelper } from '../../test-util/CoreTestHelper'; +import assert from 'assert'; +import { TraceLogger } from './fixtures/logger/TraceLogger'; + +describe('test/Logger.test.ts', () => { + + + let modules: Array; + beforeEach(async () => { + modules = await CoreTestHelper.prepareModules([ + path.join(__dirname, '..'), + path.join(__dirname, 'fixtures/logger'), + ]); + }); + + afterEach(async () => { + for (const module of modules) { + await LoadUnitFactory.destroyLoadUnit(module.loadUnit); + await LoadUnitInstanceFactory.destroyLoadUnitInstance(module); + } + }); + + describe('Pointcut', () => { + it('should work', async () => { + const traceLogger = await CoreTestHelper.getObject(TraceLogger); + traceLogger.info('info %s', ); + }); + }); + + // describe('Logger Define', () => { + + // }); + + // describe('Logger Manager', () => { + + // }); + +}); diff --git a/core/logger/test/fixtures/logger/TraceLogger.ts b/core/logger/test/fixtures/logger/TraceLogger.ts new file mode 100644 index 00000000..f86ec580 --- /dev/null +++ b/core/logger/test/fixtures/logger/TraceLogger.ts @@ -0,0 +1,6 @@ +import { BaseLogger, LoggerDecorator } from '../../..'; + +@LoggerDecorator({ + file: 'trace.log', +}) +export class TraceLogger extends BaseLogger{} diff --git a/core/logger/tsconfig.json b/core/logger/tsconfig.json new file mode 100644 index 00000000..64b22405 --- /dev/null +++ b/core/logger/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "baseUrl": "./" + }, + "exclude": [ + "dist", + "node_modules", + "test" + ] +} diff --git a/core/logger/tsconfig.pub.json b/core/logger/tsconfig.pub.json new file mode 100644 index 00000000..64b22405 --- /dev/null +++ b/core/logger/tsconfig.pub.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "baseUrl": "./" + }, + "exclude": [ + "dist", + "node_modules", + "test" + ] +}