├── .editorconfig
├── .eslintrc.json
├── .github
├── renovate.json
└── workflows
│ ├── ci.yml
│ └── publish.yml
├── .gitignore
├── .prettierrc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── jest.config.ts
├── lerna.json
├── package.json
├── packages
└── core
│ ├── README.md
│ ├── jest.config.ts
│ ├── nest-cli.json
│ ├── package.json
│ ├── src
│ ├── __tests__
│ │ ├── __fixtures__
│ │ │ └── .gitkeep
│ │ ├── lib-usage.test.ts
│ │ └── log4js.module.test.ts
│ ├── index.ts
│ ├── log4js.classes.ts
│ ├── log4js.constants.ts
│ ├── log4js.extentions.ts
│ ├── log4js.module.ts
│ ├── log4js.options.ts
│ └── log4js.providers.ts
│ ├── tsconfig.json
│ └── yarn.lock
├── tsconfig.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | max_line_length = off
14 | trim_trailing_whitespace = false
15 |
16 | [*.py]
17 | indent_size = 4
18 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "parserOptions": {
4 | "sourceType": "module"
5 | },
6 | "plugins": [
7 | "@typescript-eslint/eslint-plugin"
8 | ],
9 | "extends": [
10 | "plugin:@typescript-eslint/eslint-recommended",
11 | "plugin:@typescript-eslint/recommended",
12 | "prettier"
13 | ],
14 | "root": true,
15 | "env": {
16 | "node": true
17 | },
18 | "rules": {
19 | "@typescript-eslint/interface-name-prefix": "off",
20 | "@typescript-eslint/explicit-function-return-type": "off",
21 | "@typescript-eslint/no-explicit-any": "off",
22 | "@typescript-eslint/explicit-module-boundary-types": "off",
23 | "@typescript-eslint/no-unused-vars": "off",
24 | "@typescript-eslint/ban-types": "off"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "semanticCommits": "enabled",
3 | "packageRules": [
4 | {
5 | "updateTypes": [
6 | "minor",
7 | "patch",
8 | "pin",
9 | "digest"
10 | ],
11 | "automerge": true
12 | },
13 | {
14 | "depTypeList": [
15 | "dependencies",
16 | "devDependencies"
17 | ],
18 | "automerge": true
19 | }
20 | ],
21 | "extends": [
22 | "config:base"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | ci:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: SCM
10 | uses: actions/checkout@v2
11 | - name: Setup Node Environment
12 | uses: actions/setup-node@v1
13 | with:
14 | node-version: 14
15 | - name: Install Dependencies and Build
16 | run: |
17 | yarn
18 | yarn bootstrap
19 | yarn test:cov
20 | - name: Upload coverage to Codecov
21 | uses: codecov/codecov-action@v1
22 | with:
23 | token: ${{secrets.CODECOV_TOKEN}}
24 | file: ./reports/coverage/lcov.info
25 | flags: unittests
26 | name: codecov-umbrella
27 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: publish
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | publish-npm:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: SCM
13 | uses: actions/checkout@v2
14 | - name: Setup Node Environment
15 | uses: actions/setup-node@v1
16 | with:
17 | node-version: 14
18 | - name: Install Dependencies and Build
19 | run: |
20 | yarn
21 | yarn bootstrap
22 | yarn build
23 | - name: Semantic Release
24 | run: |
25 | echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> ~/.npmrc
26 | yarn release
27 | env:
28 | GH_TOKEN: ${{ secrets.GH_TOKEN }}
29 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
30 | NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/node,code,jetbrains+all
3 | # Edit at https://www.gitignore.io/?templates=node,code,jetbrains+all
4 |
5 | ### Code ###
6 | .vscode/*
7 | !.vscode/settings.json
8 | !.vscode/tasks.json
9 | !.vscode/launch.json
10 | !.vscode/extensions.json
11 |
12 | ### JetBrains+all ###
13 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
14 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
15 |
16 | # User-specific stuff
17 | .idea/**/workspace.xml
18 | .idea/**/tasks.xml
19 | .idea/**/usage.statistics.xml
20 | .idea/**/dictionaries
21 | .idea/**/shelf
22 |
23 | # Generated files
24 | .idea/**/contentModel.xml
25 |
26 | # Sensitive or high-churn files
27 | .idea/**/dataSources/
28 | .idea/**/dataSources.ids
29 | .idea/**/dataSources.local.xml
30 | .idea/**/sqlDataSources.xml
31 | .idea/**/dynamic.xml
32 | .idea/**/uiDesigner.xml
33 | .idea/**/dbnavigator.xml
34 |
35 | # Gradle
36 | .idea/**/gradle.xml
37 | .idea/**/libraries
38 |
39 | # Gradle and Maven with auto-import
40 | # When using Gradle or Maven with auto-import, you should exclude module files,
41 | # since they will be recreated, and may cause churn. Uncomment if using
42 | # auto-import.
43 | # .idea/modules.xml
44 | # .idea/*.iml
45 | # .idea/modules
46 | # *.iml
47 | # *.ipr
48 |
49 | # CMake
50 | cmake-build-*/
51 |
52 | # Mongo Explorer plugin
53 | .idea/**/mongoSettings.xml
54 |
55 | # File-based project format
56 | *.iws
57 |
58 | # IntelliJ
59 | out/
60 |
61 | # mpeltonen/sbt-idea plugin
62 | .idea_modules/
63 |
64 | # JIRA plugin
65 | atlassian-ide-plugin.xml
66 |
67 | # Cursive Clojure plugin
68 | .idea/replstate.xml
69 |
70 | # Crashlytics plugin (for Android Studio and IntelliJ)
71 | com_crashlytics_export_strings.xml
72 | crashlytics.properties
73 | crashlytics-build.properties
74 | fabric.properties
75 |
76 | # Editor-based Rest Client
77 | .idea/httpRequests
78 |
79 | # Android studio 3.1+ serialized cache file
80 | .idea/caches/build_file_checksums.ser
81 |
82 | ### JetBrains+all Patch ###
83 | # Ignores the whole .idea folder and all .iml files
84 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
85 |
86 | .idea/
87 |
88 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
89 |
90 | *.iml
91 | modules.xml
92 | .idea/misc.xml
93 | *.ipr
94 |
95 | # Sonarlint plugin
96 | .idea/sonarlint
97 |
98 | ### Node ###
99 | # Logs
100 | logs
101 | *.log
102 | npm-debug.log*
103 | yarn-debug.log*
104 | yarn-error.log*
105 | lerna-debug.log*
106 |
107 | # Diagnostic reports (https://nodejs.org/api/report.html)
108 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
109 |
110 | # Runtime data
111 | pids
112 | *.pid
113 | *.seed
114 | *.pid.lock
115 |
116 | # Directory for instrumented libs generated by jscoverage/JSCover
117 | lib-cov
118 |
119 | # Coverage directory used by tools like istanbul
120 | coverage
121 | *.lcov
122 |
123 | # nyc test coverage
124 | .nyc_output
125 |
126 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
127 | .grunt
128 |
129 | # Bower dependency directory (https://bower.io/)
130 | bower_components
131 |
132 | # node-waf configuration
133 | .lock-wscript
134 |
135 | # Compiled binary addons (https://nodejs.org/api/addons.html)
136 | build/Release
137 |
138 | # Dependency directories
139 | node_modules/
140 | jspm_packages/
141 |
142 | # TypeScript v1 declaration files
143 | typings/
144 |
145 | # TypeScript cache
146 | *.tsbuildinfo
147 |
148 | # Optional npm cache directory
149 | .npm
150 |
151 | # Optional eslint cache
152 | .eslintcache
153 |
154 | # Optional REPL history
155 | .node_repl_history
156 |
157 | # Output of 'npm pack'
158 | *.tgz
159 |
160 | # Yarn Integrity file
161 | .yarn-integrity
162 |
163 | # dotenv environment variables file
164 | .env
165 | .env.test
166 |
167 | # parcel-bundler cache (https://parceljs.org/)
168 | .cache
169 |
170 | # next.js build output
171 | .next
172 |
173 | # nuxt.js build output
174 | .nuxt
175 |
176 | # rollup.js default build output
177 | dist/
178 |
179 | # Uncomment the public line if your project uses Gatsby
180 | # https://nextjs.org/blog/next-9-1#public-directory-support
181 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav
182 | # public
183 |
184 | # Storybook build outputs
185 | .out
186 | .storybook-out
187 |
188 | # vuepress build output
189 | .vuepress/dist
190 |
191 | # Serverless directories
192 | .serverless/
193 |
194 | # FuseBox cache
195 | .fusebox/
196 |
197 | # DynamoDB Local files
198 | .dynamodb/
199 |
200 | # Temporary folders
201 | tmp/
202 | temp/
203 |
204 | # End of https://www.gitignore.io/api/node,code,jetbrains+all
205 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "arrowParens": "always",
4 | "proseWrap": "never",
5 | "singleQuote": true,
6 | "trailingComma": "none",
7 | "printWidth": 120
8 | }
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.5.3](https://github.com/nest-x/nestx-log4js/compare/v1.5.2...v1.5.3) (2025-02-22)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * **deps:** update dependency rxjs to v7.8.2 ([#1315](https://github.com/nest-x/nestx-log4js/issues/1315)) ([5b8a76b](https://github.com/nest-x/nestx-log4js/commit/5b8a76b4743b5074e017cbf82504714aba69b5ff))
7 |
8 | ## [1.5.2](https://github.com/nest-x/nestx-log4js/compare/v1.5.1...v1.5.2) (2023-03-16)
9 |
10 |
11 | ### Bug Fixes
12 |
13 | * **deps:** update dependency log4js to v6.9.1 ([875b24e](https://github.com/nest-x/nestx-log4js/commit/875b24e278f0e39bced8a17ca4677e27cb8d4913))
14 |
15 | ## [1.5.1](https://github.com/nest-x/nestx-log4js/compare/v1.5.0...v1.5.1) (2022-01-22)
16 |
17 |
18 | ### Bug Fixes
19 |
20 | * **deps:** update dependency log4js to v6.4.0 [security] ([6b8e11c](https://github.com/nest-x/nestx-log4js/commit/6b8e11c2003e6ace33b3ffb63c08e9c8ccb95fec))
21 |
22 | # [1.5.0](https://github.com/nest-x/nestx-log4js/compare/v1.4.0...v1.5.0) (2021-04-03)
23 |
24 |
25 | ### Features
26 |
27 | * support error trace ([#452](https://github.com/nest-x/nestx-log4js/issues/452)) ([a16cbef](https://github.com/nest-x/nestx-log4js/commit/a16cbef8db6b9cf0187dbc72eeb2d33110cc4c56))
28 |
29 | # [1.4.0](https://github.com/nest-x/nestx-log4js/compare/v1.3.12...v1.4.0) (2021-03-31)
30 |
31 |
32 | ### Features
33 |
34 | * support error trace ([c96a22a](https://github.com/nest-x/nestx-log4js/commit/c96a22af0e77902218561f05a5d98f20e93130db))
35 |
36 | ## [1.3.12](https://github.com/nest-x/nestx-log4js/compare/v1.3.11...v1.3.12) (2020-12-24)
37 |
38 |
39 | ### Bug Fixes
40 |
41 | * **logger:** correct method case ([a59398d](https://github.com/nest-x/nestx-log4js/commit/a59398d2526ad386e836fb6d4c961d84e8f62edc))
42 |
43 | ## [1.3.11](https://github.com/nest-x/nestx-log4js/compare/v1.3.10...v1.3.11) (2020-12-24)
44 |
45 |
46 | ### Bug Fixes
47 |
48 | * **logger:** add static and instance method `getTimestamp` ([10b78d1](https://github.com/nest-x/nestx-log4js/commit/10b78d13bd07499635093d457e5cc772e296f0e4))
49 |
50 | ## [1.3.10](https://github.com/nest-x/nestx-log4js/compare/v1.3.9...v1.3.10) (2020-12-24)
51 |
52 |
53 | ### Bug Fixes
54 |
55 | * **deps:** move deps to dev/peerDependencies ([49912f5](https://github.com/nest-x/nestx-log4js/commit/49912f5ce83ad45b0f6ab8a94657770e635c873e)), closes [#342](https://github.com/nest-x/nestx-log4js/issues/342)
56 |
57 | ## [1.3.9](https://github.com/nest-x/nestx-log4js/compare/v1.3.8...v1.3.9) (2020-12-21)
58 |
59 |
60 | ### Bug Fixes
61 |
62 | * **deps:** update nest monorepo to v7.6.4 ([9b1d97e](https://github.com/nest-x/nestx-log4js/commit/9b1d97e8ccaf6e0466094c25eec1bf5a91bef3d5))
63 |
64 | ## [1.3.8](https://github.com/nest-x/nestx-log4js/compare/v1.3.7...v1.3.8) (2020-12-17)
65 |
66 |
67 | ### Bug Fixes
68 |
69 | * **deps:** update nest monorepo to v7.6.3 ([4bc27ae](https://github.com/nest-x/nestx-log4js/commit/4bc27ae9dad2b3eeef5134f0d419ddcf48f93fab))
70 |
71 | ## [1.3.7](https://github.com/nest-x/nestx-log4js/compare/v1.3.6...v1.3.7) (2020-12-17)
72 |
73 |
74 | ### Bug Fixes
75 |
76 | * **deps:** update nest monorepo to v7.6.2 ([dbcaa0a](https://github.com/nest-x/nestx-log4js/commit/dbcaa0a7faebe08b20e71a4bcf62de79b3775016))
77 |
78 | ## [1.3.6](https://github.com/nest-x/nestx-log4js/compare/v1.3.5...v1.3.6) (2020-12-17)
79 |
80 |
81 | ### Bug Fixes
82 |
83 | * **deps:** bump nestjs/common dependencies ([76dab38](https://github.com/nest-x/nestx-log4js/commit/76dab3890f3298587632b2c747b9f4a495cec8e8))
84 |
85 | ## [1.3.5](https://github.com/nest-x/nestx-log4js/compare/v1.3.4...v1.3.5) (2020-12-10)
86 |
87 |
88 | ### Bug Fixes
89 |
90 | * **deps:** update nest monorepo to v7.6.1 ([5558091](https://github.com/nest-x/nestx-log4js/commit/55580912f9e5ad3f26a6b8993c74787941bcb439))
91 |
92 | ## [1.3.4](https://github.com/nest-x/nestx-log4js/compare/v1.3.3...v1.3.4) (2020-12-10)
93 |
94 |
95 | ### Bug Fixes
96 |
97 | * **deps:** update nest monorepo to v7.6.0 ([ff12075](https://github.com/nest-x/nestx-log4js/commit/ff12075b58bcfd9fcdcc0ceafd85066a6a29172f))
98 |
99 | ## [1.3.3](https://github.com/nest-x/nestx-log4js/compare/v1.3.2...v1.3.3) (2020-11-23)
100 |
101 |
102 | ### Bug Fixes
103 |
104 | * **deps:** update nest monorepo to v7.5.5 ([99cf84c](https://github.com/nest-x/nestx-log4js/commit/99cf84c30a73d9a873e6d878135310566bd83e36))
105 |
106 | ## [1.3.2](https://github.com/nest-x/nestx-log4js/compare/v1.3.1...v1.3.2) (2020-11-18)
107 |
108 |
109 | ### Bug Fixes
110 |
111 | * **deps:** update nest monorepo to v7.5.4 ([464bc4c](https://github.com/nest-x/nestx-log4js/commit/464bc4caa8631831bf9dda31fcf7ebdccf0d5d0e))
112 |
113 | ## [1.3.1](https://github.com/nest-x/nestx-log4js/compare/v1.3.0...v1.3.1) (2020-11-17)
114 |
115 |
116 | ### Bug Fixes
117 |
118 | * **deps:** update nest monorepo to v7.5.3 ([d44a50f](https://github.com/nest-x/nestx-log4js/commit/d44a50fb353576423e70a30a75d006fbdecf5f6d))
119 |
120 | # [1.3.0](https://github.com/nest-x/nestx-log4js/compare/v1.2.1...v1.3.0) (2020-11-16)
121 |
122 |
123 | ### Features
124 |
125 | * **core:** support file depth upgrade ([#300](https://github.com/nest-x/nestx-log4js/issues/300)) ([7cfd258](https://github.com/nest-x/nestx-log4js/commit/7cfd258670da28ef7ae9d316f97a5e6bfdfccc49))
126 |
127 | ## [1.2.1](https://github.com/nest-x/nestx-log4js/compare/v1.2.0...v1.2.1) (2020-11-14)
128 |
129 |
130 | ### Bug Fixes
131 |
132 | * add padding for default layout `LEVEL` field ([a6e57cc](https://github.com/nest-x/nestx-log4js/commit/a6e57cc8a9ebbf2748a91c0f0686bef94e69979c))
133 |
134 | # [1.2.0](https://github.com/nest-x/nestx-log4js/compare/v1.1.4...v1.2.0) (2020-11-14)
135 |
136 |
137 | ### Features
138 |
139 | * update default layout ([a2d54df](https://github.com/nest-x/nestx-log4js/commit/a2d54dfd4bd6b554f3ecec63ab647e732b757929))
140 |
141 | ## [1.1.4](https://github.com/nest-x/nestx-log4js/compare/v1.1.3...v1.1.4) (2020-11-13)
142 |
143 |
144 | ### Bug Fixes
145 |
146 | * **deps:** update nest monorepo to v7.5.2 ([63318d7](https://github.com/nest-x/nestx-log4js/commit/63318d7554a480692a824b8cd8b9b41ec049f904))
147 |
148 | ## [1.1.3](https://github.com/nest-x/nestx-log4js/compare/v1.1.2...v1.1.3) (2020-11-02)
149 |
150 |
151 | ### Bug Fixes
152 |
153 | * **deps:** update nest monorepo to v7.5.1 ([91ffd0a](https://github.com/nest-x/nestx-log4js/commit/91ffd0a4104308c3d22cb822501b3c0b636b7769))
154 |
155 | ## [1.1.2](https://github.com/nest-x/nestx-log4js/compare/v1.1.1...v1.1.2) (2020-11-02)
156 |
157 |
158 | ### Bug Fixes
159 |
160 | * **deps:** update nest monorepo to v7.5.0 ([bf537b4](https://github.com/nest-x/nestx-log4js/commit/bf537b4212f71547229af58b9a1945bc876c388c))
161 |
162 | ## [1.1.1](https://github.com/nest-x/nestx-log4js/compare/v1.1.0...v1.1.1) (2020-10-06)
163 |
164 |
165 | ### Bug Fixes
166 |
167 | * **core:** remove new line in default pattern ([620ec02](https://github.com/nest-x/nestx-log4js/commit/620ec0282187d04ef6e6b1c3f66d4ac59591a1ad))
168 |
169 | # [1.1.0](https://github.com/nest-x/nestx-log4js/compare/v1.0.0...v1.1.0) (2020-10-06)
170 |
171 |
172 | ### Features
173 |
174 | * **core:** update default pattern ([#255](https://github.com/nest-x/nestx-log4js/issues/255)) ([80cf7a0](https://github.com/nest-x/nestx-log4js/commit/80cf7a0cf5976ed58358fddb86e9fd8f6605653d))
175 |
176 | # 1.0.0 (2020-10-03)
177 |
178 |
179 | ### Bug Fixes
180 |
181 | * **deps:** pin dependencies ([#1](https://github.com/nest-x/nestx-log4js/issues/1)) ([37b5018](https://github.com/nest-x/nestx-log4js/commit/37b5018384c1053a9309491475c15b253f49f04c))
182 | * **deps:** update dependency amqplib to ^0.6.0 ([29a3ce8](https://github.com/nest-x/nestx-log4js/commit/29a3ce8a9dfef52c01e5e9318a12828302935238))
183 | * **deps:** update dependency rxjs to v6.5.5 ([16678ca](https://github.com/nest-x/nestx-log4js/commit/16678caf62665e10575573cac0e0a926fe1d7db0))
184 | * **deps:** update dependency rxjs to v6.6.0 ([2e4b59a](https://github.com/nest-x/nestx-log4js/commit/2e4b59a04466e4df742d8351d13b503cbef500ae))
185 | * **deps:** update dependency rxjs to v6.6.2 ([7ed30e9](https://github.com/nest-x/nestx-log4js/commit/7ed30e9cd6cb26cb3ec2c86d74a3c27fff0683cd))
186 | * **deps:** update dependency rxjs to v6.6.3 ([d6e7831](https://github.com/nest-x/nestx-log4js/commit/d6e7831ba791497014ebd9b73fe8f74f3736d340))
187 | * **deps:** update nest monorepo to v6.11.11 ([#10](https://github.com/nest-x/nestx-log4js/issues/10)) ([709bac0](https://github.com/nest-x/nestx-log4js/commit/709bac0c23e295d1671af73258b52cc459d94206))
188 | * **deps:** update nest monorepo to v6.11.9 ([#8](https://github.com/nest-x/nestx-log4js/issues/8)) ([f1e2c62](https://github.com/nest-x/nestx-log4js/commit/f1e2c6272ad5c7e1b618d7c16d40260734dc466e))
189 | * **deps:** update nest monorepo to v7.0.10 ([ffd0bf9](https://github.com/nest-x/nestx-log4js/commit/ffd0bf9634de4b0e9f9c5f2e89b65ba197c3f74e))
190 | * **deps:** update nest monorepo to v7.0.11 ([e5c1ff3](https://github.com/nest-x/nestx-log4js/commit/e5c1ff331e6f0f91e09aeaff80926a3405f978a7))
191 | * **deps:** update nest monorepo to v7.0.13 ([b664499](https://github.com/nest-x/nestx-log4js/commit/b664499fcae7ca450b81e0b9bd381182f6ad35e6))
192 | * **deps:** update nest monorepo to v7.0.2 ([#19](https://github.com/nest-x/nestx-log4js/issues/19)) ([31a8442](https://github.com/nest-x/nestx-log4js/commit/31a84422eb8a77cf4248c4018afa9d3f2a7770bd))
193 | * **deps:** update nest monorepo to v7.0.3 ([#21](https://github.com/nest-x/nestx-log4js/issues/21)) ([68ef7af](https://github.com/nest-x/nestx-log4js/commit/68ef7af7e7859ebaccd3d5898347613aa235a74f))
194 | * **deps:** update nest monorepo to v7.0.4 ([bdb8af7](https://github.com/nest-x/nestx-log4js/commit/bdb8af7556ac390c63a81b7e047994e79306da25))
195 | * **deps:** update nest monorepo to v7.0.5 ([59b408d](https://github.com/nest-x/nestx-log4js/commit/59b408d4f6335ad27b4a5a78eadcc2bbde1d5eff))
196 | * **deps:** update nest monorepo to v7.0.6 ([faa6511](https://github.com/nest-x/nestx-log4js/commit/faa6511aa04f33899034617beb78c49a7515d8ef))
197 | * **deps:** update nest monorepo to v7.0.7 ([#46](https://github.com/nest-x/nestx-log4js/issues/46)) ([e09bd2c](https://github.com/nest-x/nestx-log4js/commit/e09bd2c750a86949a5e4d0639ea1bd1cd66245ed))
198 | * **deps:** update nest monorepo to v7.0.8 ([7ca0c22](https://github.com/nest-x/nestx-log4js/commit/7ca0c223dfb5d6952f5d613e82e040283d5d901b))
199 | * **deps:** update nest monorepo to v7.0.9 ([4f4b599](https://github.com/nest-x/nestx-log4js/commit/4f4b599ee710062666da094db831dfc1278393d6))
200 | * **deps:** update nest monorepo to v7.1.0 ([835cf70](https://github.com/nest-x/nestx-log4js/commit/835cf7055aaa2fb5284478434a9db5991bd3ba37))
201 | * **deps:** update nest monorepo to v7.1.1 ([8c8308a](https://github.com/nest-x/nestx-log4js/commit/8c8308a66edc202a9a0906ad935fa3245bdfe1c5))
202 | * **deps:** update nest monorepo to v7.1.2 ([b270623](https://github.com/nest-x/nestx-log4js/commit/b270623cbcb90eb1135dfe3f762c0f2e26e930dc))
203 | * **deps:** update nest monorepo to v7.1.3 ([63b8ed6](https://github.com/nest-x/nestx-log4js/commit/63b8ed6b9b7ddcf48eeef5d91aa9573f65fa0947))
204 | * **deps:** update nest monorepo to v7.3.0 ([858424d](https://github.com/nest-x/nestx-log4js/commit/858424dae363e28975933264a64cb15340f2cfe9))
205 | * **deps:** update nest monorepo to v7.3.1 ([e39ec76](https://github.com/nest-x/nestx-log4js/commit/e39ec76bfde4a3619adec09737570202b4ecdbab))
206 | * **deps:** update nest monorepo to v7.3.2 ([1dd7eb2](https://github.com/nest-x/nestx-log4js/commit/1dd7eb24e254a8e8ec8d36875da497b68b797512))
207 | * **deps:** update nest monorepo to v7.4.0 ([00329bb](https://github.com/nest-x/nestx-log4js/commit/00329bbf4b98e395476666b6d0eb32b23c98c13e))
208 | * **deps:** update nest monorepo to v7.4.1 ([6f9e383](https://github.com/nest-x/nestx-log4js/commit/6f9e383112036880f75c1584021b94b5db98d437))
209 | * **deps:** update nest monorepo to v7.4.2 ([3faf31a](https://github.com/nest-x/nestx-log4js/commit/3faf31a13fb1ca5c66ab14ea92a0209dfd92e2e2))
210 | * **deps:** update nest monorepo to v7.4.3 ([99f0f45](https://github.com/nest-x/nestx-log4js/commit/99f0f45de7cd71a225d0dcdcd698c35effdaf14f))
211 | * **deps:** update nest monorepo to v7.4.4 ([2f9b1c7](https://github.com/nest-x/nestx-log4js/commit/2f9b1c77a0b1ee3df6c3a4d824b617379e426405))
212 |
213 |
214 | ### Features
215 |
216 | * core module setup ([#249](https://github.com/nest-x/nestx-log4js/issues/249)) ([907fe87](https://github.com/nest-x/nestx-log4js/commit/907fe8727efbc63926f6b9b6a98c157cce6c7bcb))
217 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2020 Aquariuslt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nestx-log4js
2 |
3 | [](https://github.com/nest-x/nestx-log4js)
4 | [](https://codecov.io/gh/nest-x/nestx-log4js)
5 | [](https://github.com/semantic-release/semantic-release)
6 |
7 |
8 | Provide log4js module as NestJS module
9 |
10 | This is root of `@nestx-log4js` monorepo.
11 |
12 | To Get Started, please read [`@nestx-log4js/core` Documentation](./packages/core/)
13 |
14 |
15 | ## Core Module Documentation
16 |
17 | `log4js` as NestJS Module.
18 |
19 |
20 |
21 | ## Features
22 |
23 | - Provide `log4js` wrapper as NestJS Global Module
24 | - Provide `Log4jsLogger` instance for replacement logger usage
25 |
26 |
27 |
28 |
29 | ## Installation
30 |
31 | ```shell
32 | yarn add @nestx-log4js/core
33 | ```
34 |
35 |
36 |
37 |
38 | ## Usage
39 |
40 |
41 | ### Just want to use `log4js`?
42 |
43 | > Since logger is a special service in NestJS, we suppose
44 | > import `Log4jsModule` and manual call `app.useLogger(app.get(Log4jsLogger))`
45 |
46 |
47 | **app.module.ts**
48 |
49 | ```typescript
50 | import { Module } from '@nestjs/common';
51 | import { Log4jsModule } from '@nestx-log4js/core';
52 |
53 |
54 | @Module({
55 | imports: [
56 | Log4jsModule.forRoot()
57 | ]
58 | })
59 | export class AppModule {}
60 | ```
61 |
62 | **bootstrap.ts**
63 |
64 | ```typescript
65 | import { NestFactory } from '@nestjs/core';
66 | import { AppModule } from './app.module';
67 | import { Log4jsLogger } from '@nestx-log4js/core';
68 |
69 | async function bootstrap() {
70 | const app = await NestFactory.create(AppModule);
71 |
72 | app.useLogger(app.get(Log4jsLogger));
73 | await app.listen(3000);
74 | }
75 | bootstrap();
76 | ```
77 |
78 | > For more details, you can refer unit tests in source code
79 |
80 |
81 | ### Initial `Log4jsModule` with AsyncOptions (Production Usage)
82 |
83 | > You might want to use different appender (e.g. file/dateFile appender)
84 | > in real production usage and initial in your ConfigService/LoggerOnlyConfigService
85 |
86 |
87 | **app.module.ts**
88 |
89 | ```typescript
90 | import { Module } from '@nestjs/common';
91 | import { Log4jsModule } from '@nestx-log4js/core';
92 |
93 | // import your ConfigService/LoggerConfigService
94 |
95 | @Module({
96 | imports: [
97 | Log4js.forRootAsync({
98 | inject: [ConfigService],
99 | useFactory: (config: ConfigService) => config.getLog4jsOptions() // config.getLog4jsOptions should return valid Log4jsOptions
100 | })
101 | ]
102 | })
103 | export class AppModule {}
104 | ```
105 |
106 |
107 | ## Bundled Layout & Appenders
108 |
109 | When using `Log4jsModule.forRoot()` and no spec any appenders and layouts,
110 |
111 | It will use default below layouts:
112 |
113 | ```typescript
114 | export const LOG4JS_DEFAULT_LAYOUT = {
115 | type: 'pattern',
116 | // log4js default pattern %d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n
117 | // we use process id instead thread id
118 | pattern: '%[%d{yyyy-MM-dd hh:mm:ss:SSS} %p --- [%15.15x{name}]%] %40.40f{3} : %m',
119 | tokens: {
120 | name: (logEvent) => {
121 | return (logEvent.context && logEvent.context['name']) || '-';
122 | }
123 | }
124 | };
125 |
126 | export const LOG4JS_NO_COLOUR_DEFAULT_LAYOUT = {
127 | type: 'pattern',
128 | // log4js default pattern %d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n
129 | // we use process id instead thread id
130 | pattern: '%d{yyyy-MM-dd hh:mm:ss:SSS} %p --- [%15.15x{name}] %40.40f{3} : %m',
131 | tokens: {
132 | name: (logEvent) => {
133 | return (logEvent.context && logEvent.context['name']) || '-';
134 | }
135 | }
136 | };
137 |
138 |
139 |
140 | export const LOG4JS_DEFAULT_CONFIG: Configuration = {
141 | appenders: {
142 | stdout: {
143 | type: 'stdout',
144 | layout: LOG4JS_DEFAULT_LAYOUT
145 | },
146 | file: {
147 | type: 'file',
148 | filename: './logs/application.log',
149 | maxLogSize: 20 * 1024 * 1024, // maxLogSize use bytes ad unit
150 | backups: 10, // default use 5 so 1KB file size total rotating
151 | layout: LOG4JS_NO_COLOUR_DEFAULT_LAYOUT
152 | }
153 | },
154 | categories: {
155 | default: {
156 | enableCallStack: true,
157 | appenders: ['stdout', 'file'],
158 | level: 'debug'
159 | }
160 | }
161 | };
162 |
163 | ```
164 |
165 | It will use default below layouts (from spring boot default log pattern without process id)
166 |
167 | You can refer to [SpringBoot logging features](https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/boot-features-logging.html)
168 |
169 | ```
170 |
171 | 2020-11-14 15:47:24:486 INFO --- [ NestJS] core/src/log4js.classes.ts : log using nestjs as category
172 | 2020-11-14 15:47:24:486 INFO --- [ -] core/src/log4js.classes.ts : log using none as category
173 | 2020-11-14 15:47:24:490 INFO --- [ NestJS] core/src/log4js.classes.ts : log using nestjs as category
174 | 2020-11-14 15:47:24:490 WARN --- [ -] src/__tests__/log4js.module.test.ts : log using none as category
175 |
176 | ```
177 |
178 |
179 |
180 |
181 | > Tips: You are using grok pattern via filebeat/other sidecar log agent? You can use below grok pattern:
182 | > %{TIMESTAMP_ISO8601:server_time}\s*%{LOGLEVEL:level}\s*---\s*\[\s*%{NOTSPACE:context}\]\s*%{NOTSPACE:file_path}\s*:\s*%{GREEDYDATA:content}
183 | >
184 | > It will split to friendly format (you can update alias yourself via grok document)
185 | > - server_time
186 | > - level
187 | > - context
188 | > - file_path
189 | > - content
190 |
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from '@jest/types';
2 |
3 | const rootJestConfig: Config.InitialOptions = {
4 | moduleFileExtensions: [
5 | 'ts',
6 | 'js',
7 | 'json'
8 | ],
9 | transform: {
10 | '^.+\\.(t|j)s$': 'ts-jest'
11 | },
12 | collectCoverageFrom: [
13 | '/src/*.ts',
14 | '!/src/__tests__/**/*.ts',
15 | '!/src/shared/**/*.ts',
16 | '!/src/index.ts',
17 | '/packages/*/src/*.ts',
18 | '!/packages/*/src/__tests__/**/*.ts',
19 | '!/packages/*/src/shared/**/*.ts',
20 | '!/packages/*/src/index.ts'
21 | ],
22 | testMatch: [
23 | '/src/**/*.test.ts',
24 | '/packages/*/src/**/*.test.ts'
25 | ],
26 | testEnvironment: 'node',
27 | coverageDirectory: '/reports/coverage'
28 | };
29 |
30 | export default rootJestConfig;
31 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "packages/*"
4 | ],
5 | "version": "1.5.3",
6 | "npmClient": "yarn"
7 | }
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nestx-log4js",
3 | "version": "1.5.3",
4 | "private": true,
5 | "scripts": {
6 | "bootstrap": "lerna bootstrap",
7 | "format": "prettier --write \"packages/*/src/**/*.ts\"",
8 | "lint": "eslint \"packages/*/src/**/*.ts\" --fix",
9 | "test": "jest",
10 | "test:cov": "jest --coverage",
11 | "build": "lerna run build",
12 | "release": "semantic-release"
13 | },
14 | "dependencies": {
15 | "@nestjs/common": "8.4.7",
16 | "@nestjs/core": "9.0.5",
17 | "@nestjs/platform-express": "8.4.7",
18 | "reflect-metadata": "0.2.2",
19 | "rimraf": "5.0.10",
20 | "rxjs": "7.8.2"
21 | },
22 | "devDependencies": {
23 | "@nestjs/cli": "9.4.2",
24 | "@nestjs/schematics": "9.0.4",
25 | "@nestjs/testing": "8.4.7",
26 | "@semantic-release/changelog": "6.0.3",
27 | "@semantic-release/exec": "6.0.3",
28 | "@semantic-release/git": "10.0.1",
29 | "@types/express": "5.0.3",
30 | "@types/jest": "27.5.2",
31 | "@types/node": "22.15.30",
32 | "@types/supertest": "6.0.3",
33 | "@typescript-eslint/eslint-plugin": "5.62.0",
34 | "@typescript-eslint/parser": "5.62.0",
35 | "eslint": "8.57.1",
36 | "eslint-config-prettier": "10.1.5",
37 | "eslint-plugin-import": "2.31.0",
38 | "eslint-plugin-prettier": "5.4.1",
39 | "jest": "26.6.3",
40 | "lerna": "6.6.2",
41 | "prettier": "3.5.3",
42 | "semantic-release": "19.0.5",
43 | "sinon": "20.0.0",
44 | "supertest": "7.1.1",
45 | "ts-jest": "26.5.6",
46 | "ts-loader": "9.5.2",
47 | "ts-node": "10.9.2",
48 | "tsconfig-paths": "4.2.0",
49 | "typescript": "5.8.3"
50 | },
51 | "release": {
52 | "plugins": [
53 | "@semantic-release/commit-analyzer",
54 | "@semantic-release/release-notes-generator",
55 | "@semantic-release/github",
56 | "@semantic-release/npm",
57 | "@semantic-release/changelog",
58 | [
59 | "@semantic-release/exec",
60 | {
61 | "prepareCmd": "lerna exec --concurrency 1 -- npm version ${nextRelease.version} && lerna version ${nextRelease.version} --no-git-tag-version --no-push --amend --yes",
62 | "publishCmd": "lerna exec --concurrency 1 -- npm publish --access public --registry=https://registry.npmjs.org"
63 | }
64 | ],
65 | [
66 | "@semantic-release/git",
67 | {
68 | "assets": [
69 | "CHANGELOG.md",
70 | "lerna.json",
71 | "package.json",
72 | "packages/*/package.json"
73 | ],
74 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
75 | }
76 | ]
77 | ]
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/packages/core/README.md:
--------------------------------------------------------------------------------
1 | # `@nestx-log4js/core`
2 |
3 | [](https://www.npmjs.com/package/@nestx-log4js/core)
4 | [](https://github.com/nest-x/nestx-log4js)
5 | [](https://codecov.io/gh/nest-x/nestx-log4js)
6 |
7 | `log4js` as NestJS Module.
8 |
9 |
10 |
11 | ## Features
12 |
13 | - Provide `log4js` wrapper as NestJS Global Module
14 | - Provide `Log4jsLogger` instance for replacement logger usage
15 |
16 |
17 |
18 |
19 | ## Installation
20 |
21 | ```shell
22 | yarn add @nestx-log4js/core
23 | ```
24 |
25 |
26 |
27 |
28 | ## Usage
29 |
30 |
31 | ### Just want to use `log4js`?
32 |
33 | > Since logger is a special service in NestJS, we suppose
34 | > import `Log4jsModule` and manual call `app.useLogger(app.get(Log4jsLogger))`
35 |
36 |
37 | **app.module.ts**
38 |
39 | ```typescript
40 | import { Module } from '@nestjs/common';
41 | import { Log4jsModule } from '@nestx-log4js/core';
42 |
43 |
44 | @Module({
45 | imports: [
46 | Log4jsModule.forRoot()
47 | ]
48 | })
49 | export class AppModule {}
50 | ```
51 |
52 | **bootstrap.ts**
53 |
54 | ```typescript
55 | import { NestFactory } from '@nestjs/core';
56 | import { AppModule } from './app.module';
57 | import { Log4jsLogger } from '@nestx-log4js/core';
58 |
59 | async function bootstrap() {
60 | const app = await NestFactory.create(AppModule);
61 |
62 | app.useLogger(app.get(Log4jsLogger));
63 | await app.listen(3000);
64 | }
65 | bootstrap();
66 | ```
67 |
68 | > For more details, you can refer unit tests in source code
69 |
70 |
71 | ### Initial `Log4jsModule` with AsyncOptions (Production Usage)
72 |
73 | > You might want to use different appender (e.g. file/dateFile appender)
74 | > in real production usage and initial in your ConfigService/LoggerOnlyConfigService
75 |
76 |
77 | **app.module.ts**
78 |
79 | ```typescript
80 | import { Module } from '@nestjs/common';
81 | import { Log4jsModule } from '@nestx-log4js/core';
82 |
83 | // import your ConfigService/LoggerConfigService
84 |
85 | @Module({
86 | imports: [
87 | Log4js.forRootAsync({
88 | inject: [ConfigService],
89 | useFactory: (config: ConfigService) => config.getLog4jsOptions() // config.getLog4jsOptions should return valid Log4jsOptions
90 | })
91 | ]
92 | })
93 | export class AppModule {}
94 | ```
95 |
96 |
97 | ## Bundled Layout & Appenders
98 |
99 | When using `Log4jsModule.forRoot()` and no spec any appenders and layouts,
100 |
101 | It will use default below layouts:
102 |
103 | ```typescript
104 | export const LOG4JS_DEFAULT_LAYOUT = {
105 | type: 'pattern',
106 | // log4js default pattern %d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n
107 | // we use process id instead thread id
108 | pattern: '%[%d{yyyy-MM-dd hh:mm:ss:SSS} %p --- [%15.15x{name}]%] %40.40f{3} : %m',
109 | tokens: {
110 | name: (logEvent) => {
111 | return (logEvent.context && logEvent.context['name']) || '-';
112 | }
113 | }
114 | };
115 |
116 | export const LOG4JS_NO_COLOUR_DEFAULT_LAYOUT = {
117 | type: 'pattern',
118 | // log4js default pattern %d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n
119 | // we use process id instead thread id
120 | pattern: '%d{yyyy-MM-dd hh:mm:ss:SSS} %p --- [%15.15x{name}] %40.40f{3} : %m',
121 | tokens: {
122 | name: (logEvent) => {
123 | return (logEvent.context && logEvent.context['name']) || '-';
124 | }
125 | }
126 | };
127 |
128 |
129 |
130 | export const LOG4JS_DEFAULT_CONFIG: Configuration = {
131 | appenders: {
132 | stdout: {
133 | type: 'stdout',
134 | layout: LOG4JS_DEFAULT_LAYOUT
135 | },
136 | file: {
137 | type: 'file',
138 | filename: './logs/application.log',
139 | maxLogSize: 20 * 1024 * 1024, // maxLogSize use bytes ad unit
140 | backups: 10, // default use 5 so 1KB file size total rotating
141 | layout: LOG4JS_NO_COLOUR_DEFAULT_LAYOUT
142 | }
143 | },
144 | categories: {
145 | default: {
146 | enableCallStack: true,
147 | appenders: ['stdout', 'file'],
148 | level: 'debug'
149 | }
150 | }
151 | };
152 |
153 | ```
154 |
155 | It will use default below layouts (from spring boot default log pattern without process id)
156 |
157 | You can refer to [SpringBoot logging features](https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/boot-features-logging.html)
158 |
159 | ```
160 |
161 | 2020-11-14 15:47:24:486 INFO --- [ NestJS] core/src/log4js.classes.ts : log using nestjs as category
162 | 2020-11-14 15:47:24:486 INFO --- [ -] core/src/log4js.classes.ts : log using none as category
163 | 2020-11-14 15:47:24:490 INFO --- [ NestJS] core/src/log4js.classes.ts : log using nestjs as category
164 | 2020-11-14 15:47:24:490 WARN --- [ -] src/__tests__/log4js.module.test.ts : log using none as category
165 |
166 | ```
167 |
--------------------------------------------------------------------------------
/packages/core/jest.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from '@jest/types';
2 |
3 |
4 | const jestConfig: Config.InitialOptions = {
5 | moduleFileExtensions: [
6 | 'ts',
7 | 'js',
8 | 'json'
9 | ],
10 | transform: {
11 | '^.+\\.(t|j)s$': 'ts-jest'
12 | },
13 | collectCoverageFrom: [
14 | '/src/*.ts',
15 | '!/src/__tests__/**/*.ts',
16 | '!/src/shared/**/*.ts',
17 | '!/src/index.ts'
18 | ],
19 | testMatch: [
20 | '/src/**/*.test.ts'
21 | ],
22 | testEnvironment: 'node',
23 | coverageDirectory: '/reports/coverage'
24 | };
25 |
26 |
27 | export default jestConfig;
28 |
--------------------------------------------------------------------------------
/packages/core/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nestx-log4js/core",
3 | "version": "1.5.3",
4 | "description": "nestx-log4js core module",
5 | "author": "aquariuslt ",
6 | "homepage": "https://github.com/nest-x/nestx-log4js#readme",
7 | "keywords": [
8 | "nestjs",
9 | "nestx",
10 | "log4js",
11 | "logger"
12 | ],
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/nest-x/nestx-log4js.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/nest-x/nestx-log4js/issues"
19 | },
20 | "license": "MIT",
21 | "publishConfig": {
22 | "access": "public"
23 | },
24 | "files": [
25 | "dist",
26 | "index.ts"
27 | ],
28 | "main": "dist/index.js",
29 | "scripts": {
30 | "prebuild": "rimraf dist",
31 | "build": "tsc",
32 | "test": "jest",
33 | "test:cov": "jest --coverage"
34 | },
35 | "dependencies": {
36 | "log4js": "^6.1.2"
37 | },
38 | "devDependencies": {
39 | "@nestjs/cli": "9.4.2",
40 | "@nestjs/common": "8.4.7",
41 | "@nestjs/core": "9.0.5",
42 | "@nestjs/schematics": "9.0.4",
43 | "@nestjs/testing": "8.4.7",
44 | "@types/jest": "27.5.2",
45 | "@types/node": "22.15.30",
46 | "jest": "26.6.3",
47 | "proxyquire": "2.1.3",
48 | "reflect-metadata": "0.2.2",
49 | "rimraf": "5.0.10",
50 | "rxjs": "7.8.2",
51 | "ts-jest": "26.5.6",
52 | "ts-loader": "9.5.2",
53 | "ts-node": "10.9.2",
54 | "tsconfig-paths": "4.2.0",
55 | "typescript": "5.8.3"
56 | },
57 | "peerDependencies": {
58 | "@nestjs/common": "^7.0.0 || ^8.0.0",
59 | "@nestjs/core": "^7.0.0 || ^8.0.0 || ^9.0.0",
60 | "reflect-metadata": "^0.1.13 || ^0.2.0",
61 | "rxjs": "^6.5.4 || ^7.0.0"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/packages/core/src/__tests__/__fixtures__/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nest-x/nestx-log4js/4a9cc0fa7a568f3f464b76550d5bfa8a9c47feb7/packages/core/src/__tests__/__fixtures__/.gitkeep
--------------------------------------------------------------------------------
/packages/core/src/__tests__/lib-usage.test.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc this is not a nest module test.
3 | * only calling log4js and complete typings
4 | **/
5 |
6 | import * as log4js from 'log4js';
7 | import { Configuration, LoggingEvent } from 'log4js';
8 |
9 | describe('log4js usage', () => {
10 | afterEach(async (done) => {
11 | // waiting for log4js worker process shutdown
12 | // we should support graceful shutdown in nestjs/cloud-native project
13 | log4js.shutdown(() => {
14 | done();
15 | });
16 | });
17 |
18 | it('# sample usage', () => {
19 | const logger = log4js.getLogger();
20 |
21 | logger.level = 'debug';
22 | logger.debug('print from default logger');
23 | });
24 |
25 | describe('log4js configuration', () => {
26 | it('# should load configuration via config object', () => {
27 | const config: Configuration = {
28 | appenders: {
29 | out: {
30 | type: 'file',
31 | filename: './logs/log-via-config.log'
32 | },
33 | console: {
34 | type: 'stdout'
35 | }
36 | },
37 | categories: {
38 | default: {
39 | appenders: ['out', 'console'],
40 | level: 'info'
41 | },
42 | debug: {
43 | appenders: ['out', 'console'],
44 | level: 'debug'
45 | }
46 | }
47 | };
48 |
49 | log4js.configure(config);
50 |
51 | const logger = log4js.getLogger();
52 | logger.info('print from default logger (via configuration)');
53 |
54 | const debugLogger = log4js.getLogger('debug');
55 | debugLogger.debug('print from debug logger (via configuration)');
56 | });
57 | });
58 |
59 | describe('log4js layout', () => {
60 | it('# should print with pattern layout', () => {
61 | const config: Configuration = {
62 | appenders: {
63 | out: {
64 | type: 'stdout',
65 | layout: {
66 | type: 'pattern',
67 | pattern: '%d %p %c %x{user} %m%n',
68 | tokens: {
69 | user: () => {
70 | return 'alice';
71 | }
72 | }
73 | }
74 | }
75 | },
76 | categories: {
77 | default: {
78 | appenders: ['out'],
79 | level: 'debug'
80 | }
81 | }
82 | };
83 |
84 | log4js.configure(config);
85 | const logger = log4js.getLogger();
86 |
87 | logger.debug('print from debug logger (via layout)');
88 | });
89 |
90 | it('# should print with custom layout', () => {
91 | const config: Configuration = {
92 | appenders: {
93 | out: {
94 | type: 'stdout',
95 | layout: {
96 | type: 'json'
97 | }
98 | }
99 | },
100 | categories: {
101 | default: {
102 | appenders: ['out'],
103 | level: 'debug'
104 | }
105 | }
106 | };
107 |
108 | log4js.addLayout('json', () => (logEvent: LoggingEvent) => {
109 | return JSON.stringify(logEvent);
110 | });
111 | log4js.configure(config);
112 | const logger = log4js.getLogger();
113 |
114 | logger.info('print from debug logger (via layout:json)');
115 | });
116 |
117 | it('# should print with custom layout + context', () => {
118 | const config: Configuration = {
119 | appenders: {
120 | out: {
121 | type: 'stdout',
122 | layout: {
123 | type: 'json-with-context'
124 | }
125 | }
126 | },
127 | categories: {
128 | default: {
129 | appenders: ['out'],
130 | level: 'debug'
131 | }
132 | }
133 | };
134 |
135 | log4js.addLayout('json-with-context', () => (logEvent: LoggingEvent) => {
136 | const optimizeLogEvent = {
137 | ip: logEvent.context.ip,
138 | '@timestamp': logEvent.startTime.getTime(),
139 | category: logEvent.categoryName,
140 | level: logEvent.level.levelStr,
141 | data: logEvent.data
142 | };
143 | return JSON.stringify(optimizeLogEvent);
144 | });
145 | log4js.configure(config);
146 | const logger = log4js.getLogger();
147 |
148 | // most time we should add ip, env, some..other object
149 | logger.addContext('ip', '127.0.0.1');
150 |
151 | logger.info('print from debug logger (via layout:json-with-context)');
152 | });
153 | });
154 |
155 | describe('log4js file rotation', () => {
156 | it('# should enable file rotation via config', () => {
157 | const config: Configuration = {
158 | appenders: {
159 | out: {
160 | type: 'stdout'
161 | },
162 | file: {
163 | type: 'file',
164 | filename: './logs/log-with-json-context.log',
165 | maxLogSize: 200, // maxLogSize use bytes ad unit
166 | backups: 10, // default use 5 so 1KB file size total rotating
167 | layout: {
168 | type: 'json-context'
169 | }
170 | }
171 | },
172 | categories: {
173 | default: {
174 | appenders: ['out', 'file'],
175 | level: 'debug'
176 | }
177 | }
178 | };
179 |
180 | log4js.addLayout('json-context', () => (logEvent: LoggingEvent) => {
181 | const optimizeLogEvent = {
182 | ip: logEvent.context.ip,
183 | '@timestamp': logEvent.startTime.getTime(),
184 | category: logEvent.categoryName,
185 | level: logEvent.level.levelStr,
186 | data: logEvent.data
187 | };
188 | return JSON.stringify(optimizeLogEvent);
189 | });
190 | log4js.configure(config);
191 | const logger = log4js.getLogger();
192 |
193 | // most time we should add ip, env, some..other object
194 | logger.addContext('ip', '127.0.0.1');
195 |
196 | logger.info('print from debug logger (via layout:json-context)');
197 | });
198 | });
199 | });
200 |
--------------------------------------------------------------------------------
/packages/core/src/__tests__/log4js.module.test.ts:
--------------------------------------------------------------------------------
1 | import * as log4js from 'log4js';
2 | import { Test, TestingModule } from '@nestjs/testing';
3 | import { Log4jsModule } from '../log4js.module';
4 | import { Log4jsLogger } from '../log4js.classes';
5 | import { Logger } from '@nestjs/common';
6 | import { LOG4JS_OPTIONS } from '../log4js.constants';
7 | import { getLog4jsLoggerToken, getLog4jsOptionsToken } from '../log4js.options';
8 | import { parseNestModuleCallStack } from '../log4js.extentions';
9 |
10 | describe('@nestx-log4js module', () => {
11 | it('# should module define with sync-and-empty options correctly', async (done) => {
12 | const module: TestingModule = await Test.createTestingModule({
13 | imports: [Log4jsModule.forRoot()]
14 | }).compile();
15 |
16 | const app = module.createNestApplication();
17 | await app.init();
18 |
19 | const log4jsLogger = app.get(Log4jsLogger);
20 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
21 |
22 | app.useLogger(log4jsLogger);
23 |
24 | const logger = new Logger('test-log4js');
25 | logger.log('test logger logging powered by log4js');
26 |
27 | const log4jsModule = module.get(Log4jsModule);
28 | expect(log4jsModule).toBeInstanceOf(Log4jsModule);
29 |
30 | const log4jsOptions = app.get(LOG4JS_OPTIONS);
31 | expect(log4jsOptions).toBeDefined();
32 |
33 | await app.close();
34 | done();
35 | });
36 |
37 | it('# should module define with sync options correctly', async (done) => {
38 | const module: TestingModule = await Test.createTestingModule({
39 | imports: [
40 | Log4jsModule.forRoot({
41 | config: {
42 | appenders: {
43 | out: {
44 | type: 'file',
45 | filename: './logs/log-via-config.log'
46 | },
47 | console: {
48 | type: 'stdout'
49 | }
50 | },
51 | categories: {
52 | default: {
53 | appenders: ['out', 'console'],
54 | level: 'info'
55 | },
56 | debug: {
57 | appenders: ['out', 'console'],
58 | level: 'debug'
59 | }
60 | }
61 | }
62 | })
63 | ]
64 | }).compile();
65 |
66 | const app = module.createNestApplication();
67 | await app.init();
68 |
69 | const log4jsLogger = app.get(Log4jsLogger);
70 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
71 |
72 | app.useLogger(log4jsLogger);
73 |
74 | const logger = new Logger('test-log4js-for-root');
75 | logger.log('test logger logging powered by log4js');
76 |
77 | const log4jsModule = module.get(Log4jsModule);
78 | expect(log4jsModule).toBeInstanceOf(Log4jsModule);
79 |
80 | await app.close();
81 |
82 | done();
83 | });
84 |
85 | it('# should module defined with async options', async (done) => {
86 | const module: TestingModule = await Test.createTestingModule({
87 | imports: [
88 | Log4jsModule.forRootAsync({
89 | inject: [],
90 | useFactory: () => ({
91 | config: {
92 | appenders: {
93 | out: {
94 | type: 'file',
95 | filename: './logs/log-via-config-async.log'
96 | },
97 | console: {
98 | type: 'stdout'
99 | }
100 | },
101 | categories: {
102 | default: {
103 | appenders: ['out', 'console'],
104 | level: 'info'
105 | },
106 | debug: {
107 | appenders: ['out', 'console'],
108 | level: 'debug'
109 | }
110 | }
111 | }
112 | })
113 | })
114 | ]
115 | }).compile();
116 |
117 | const app = module.createNestApplication();
118 | await app.init();
119 |
120 | const log4jsLogger = app.get(Log4jsLogger);
121 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
122 |
123 | app.useLogger(log4jsLogger);
124 |
125 | const logger = new Logger('test-log4js-for-root-async');
126 | logger.verbose('test logger logging powered by log4js');
127 | logger.debug('test logger logging powered by log4js');
128 | logger.log('test logger logging powered by log4js');
129 | logger.warn('test logger logging powered by log4js');
130 | logger.error('test logger logging powered by log4js');
131 | logger.error('test logger logging powered by log4js', '& error log with trace in same line');
132 |
133 | const log4jsModule = module.get(Log4jsModule);
134 | expect(log4jsModule).toBeInstanceOf(Log4jsModule);
135 |
136 | await app.close();
137 |
138 | done();
139 | });
140 |
141 | it('# should support tracestack logging', async (done) => {
142 | const module: TestingModule = await Test.createTestingModule({
143 | imports: [
144 | Log4jsModule.forRootAsync({
145 | inject: [],
146 | useFactory: () => ({
147 | config: {
148 | appenders: {
149 | out: {
150 | type: 'file',
151 | filename: './logs/log-with-error-stack.log'
152 | },
153 | console: {
154 | type: 'stdout'
155 | }
156 | },
157 | categories: {
158 | default: {
159 | appenders: ['out', 'console'],
160 | level: 'info'
161 | },
162 | debug: {
163 | appenders: ['out', 'console'],
164 | level: 'debug'
165 | }
166 | }
167 | }
168 | })
169 | })
170 | ]
171 | }).compile();
172 |
173 | const app = module.createNestApplication();
174 | await app.init();
175 |
176 | const log4jsLogger = app.get(Log4jsLogger);
177 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
178 |
179 | app.useLogger(log4jsLogger);
180 |
181 | const log4jsModule = module.get(Log4jsModule);
182 | expect(log4jsModule).toBeInstanceOf(Log4jsModule);
183 |
184 |
185 | const logger = new Logger('test-log4js-for-error-stack');
186 | logger.error('will show error', (new Error).stack);
187 |
188 | await app.close();
189 |
190 | done();
191 | });
192 |
193 |
194 | it('# should module defined with spec name', async (done) => {
195 | const module: TestingModule = await Test.createTestingModule({
196 | imports: [
197 | Log4jsModule.forRoot({
198 | name: 'app',
199 | config: {
200 | appenders: {
201 | out: {
202 | type: 'file',
203 | filename: './logs/log-via-config.log'
204 | },
205 | console: {
206 | type: 'stdout'
207 | }
208 | },
209 | categories: {
210 | default: {
211 | appenders: ['out', 'console'],
212 | level: 'info'
213 | },
214 | debug: {
215 | appenders: ['out', 'console'],
216 | level: 'debug'
217 | }
218 | }
219 | }
220 | })
221 | ]
222 | }).compile();
223 |
224 | const app = module.createNestApplication();
225 | await app.init();
226 | const log4jsLogger = app.get(Log4jsLogger);
227 | const log4jsAliasLogger = app.get(getLog4jsLoggerToken('app'));
228 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
229 | expect(log4jsLogger).toEqual(log4jsAliasLogger);
230 |
231 | const log4jsOptions = app.get(getLog4jsOptionsToken('app'));
232 | expect(log4jsOptions).toBeDefined();
233 |
234 | const log4jsModule = module.get(Log4jsModule);
235 | expect(log4jsModule).toBeInstanceOf(Log4jsModule);
236 |
237 | await app.close();
238 |
239 | done();
240 | });
241 |
242 | it('# should use nestjs context display as category field', async (done) => {
243 | const module: TestingModule = await Test.createTestingModule({
244 | imports: [Log4jsModule.forRoot()]
245 | }).compile();
246 |
247 | const app = module.createNestApplication();
248 | await app.init();
249 |
250 | const log4jsLogger = app.get(Log4jsLogger);
251 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
252 |
253 | app.useLogger(log4jsLogger);
254 |
255 | const logger = new Logger('NestJS');
256 | logger.log('log using nestjs as category');
257 |
258 | const unnamedLogger = new Logger();
259 | unnamedLogger.log('log using none as category');
260 |
261 | await app.close();
262 | done();
263 | });
264 |
265 | it('# should support undefined context', async (done) => {
266 | const module: TestingModule = await Test.createTestingModule({
267 | imports: [Log4jsModule.forRoot()]
268 | }).compile();
269 |
270 | const app = module.createNestApplication();
271 | await app.init();
272 |
273 | const log4jsLogger = app.get(Log4jsLogger);
274 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
275 |
276 | app.useLogger(log4jsLogger);
277 |
278 | const logger = new Logger('NestJS');
279 | logger.log('log using nestjs as category');
280 |
281 | const unnamedLogger = log4js.getLogger();
282 | unnamedLogger.debug('log using none as category');
283 |
284 | await app.close();
285 | done();
286 | });
287 |
288 | it('# should support file depth in callstack parsing', async (done) => {
289 | const data = {
290 | stack:
291 | 'Error: \n' +
292 | ' at Logger._log (/ci/workspace/nestx-log4js/packages/core/node_modules/log4js/lib/logger.js:88:48)\n' +
293 | ' at Logger.log (/ci/workspace/nestx-log4js/packages/core/node_modules/log4js/lib/logger.js:73:12)\n' +
294 | ' at Logger. [as info] (/ci/workspace/nestx-log4js/packages/core/node_modules/log4js/lib/logger.js:124:10)\n' +
295 | ' at Log4jsLogger.log (/ci/workspace/nestx-log4js/packages/core/src/log4js.classes.ts:34:17)\n' +
296 | ' at Logger.callFunction (/ci/workspace/nestx-log4js/packages/core/node_modules/@nestjs/common/services/logger.service.js:69:18)\n' +
297 | ' at Logger.log (/ci/workspace/nestx-log4js/packages/core/node_modules/@nestjs/common/services/logger.service.js:25:14)\n' +
298 | ' at /ci/workspace/nestx-log4js/packages/core/src/__tests__/log4js.module.test.ts:258:12\n' +
299 | ' at Generator.next ()\n' +
300 | ' at fulfilled (/ci/workspace/nestx-log4js/packages/core/src/__tests__/log4js.module.test.ts:5:58)'
301 | };
302 |
303 | const { fileName } = parseNestModuleCallStack(data);
304 |
305 | expect(fileName).toEqual('/ci/workspace/nestx-log4js/packages/core/src/__tests__/log4js.module.test.ts');
306 |
307 | const customStackLineResult = parseNestModuleCallStack(data, 4);
308 |
309 | expect(customStackLineResult.fileName).toEqual('/ci/workspace/nestx-log4js/packages/core/src/log4js.classes.ts');
310 |
311 | done();
312 | });
313 |
314 | it('# should have `getTimestamp` function property', async (done) => {
315 | const module: TestingModule = await Test.createTestingModule({
316 | imports: [Log4jsModule.forRoot()]
317 | }).compile();
318 |
319 | const app = module.createNestApplication();
320 | await app.init();
321 |
322 | const log4jsLogger = app.get(Log4jsLogger);
323 | expect(log4jsLogger).toBeInstanceOf(Log4jsLogger);
324 |
325 | app.useLogger(log4jsLogger);
326 |
327 | expect(log4jsLogger).toHaveProperty('getTimestamp');
328 | expect(Log4jsLogger.getTimestamp).not.toBeUndefined();
329 |
330 | done();
331 | });
332 | });
333 |
--------------------------------------------------------------------------------
/packages/core/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './log4js.classes';
2 | export * from './log4js.constants';
3 | export * from './log4js.module';
4 | export * from './log4js.options';
5 | export * from './log4js.providers';
6 |
--------------------------------------------------------------------------------
/packages/core/src/log4js.classes.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, LoggerService } from '@nestjs/common';
2 | import { Logger } from 'log4js';
3 |
4 | @Injectable()
5 | export class Log4jsLogger implements LoggerService {
6 | constructor(private readonly logger: Logger) {}
7 |
8 | updateContext(context?: string) {
9 | if (context && context.length > 0) {
10 | this.logger.addContext('name', context);
11 | } else {
12 | this.logger.addContext('name', '');
13 | }
14 | }
15 |
16 | verbose(message: any, context?: string) {
17 | this.updateContext(context);
18 | this.logger.trace(message);
19 | }
20 |
21 | debug(message: any, context?: string) {
22 | this.updateContext(context);
23 | this.logger.debug(message);
24 | }
25 |
26 | log(message: any, context?: string) {
27 | this.updateContext(context);
28 | this.logger.info(message);
29 | }
30 |
31 | warn(message: any, context?: string) {
32 | this.updateContext(context);
33 | this.logger.warn(message);
34 | }
35 |
36 | error(message: any, trace?: string, context?: string) {
37 | this.updateContext(context);
38 | this.logger.error(message, trace);
39 | }
40 |
41 | static getTimestamp() {
42 | const localeStringOptions = {
43 | year: 'numeric',
44 | hour: 'numeric',
45 | minute: 'numeric',
46 | second: 'numeric',
47 | day: '2-digit',
48 | month: '2-digit'
49 | } as const;
50 | return new Date(Date.now()).toLocaleString(undefined, localeStringOptions);
51 | }
52 |
53 | getTimestamp() {
54 | return Log4jsLogger.getTimestamp();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/packages/core/src/log4js.constants.ts:
--------------------------------------------------------------------------------
1 | import { Configuration } from 'log4js';
2 |
3 | export const LOG4JS_OPTIONS = Symbol('NEST_LOG4JS_OPTIONS');
4 | export const LOG4JS_LOGGER = Symbol('NEST_LOG4JS_LOGGER');
5 |
6 | export const LOG4JS_DEFAULT_LAYOUT = {
7 | type: 'pattern',
8 | // log4js default pattern %d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n
9 | // we use process id instead thread id
10 | pattern: '%[%d{yyyy-MM-dd hh:mm:ss:SSS} %-5.5p --- [%15.15x{name}]%] %40.40f{3} : %m',
11 | tokens: {
12 | name: (logEvent) => {
13 | return (logEvent.context && logEvent.context['name']) || '-';
14 | }
15 | }
16 | };
17 |
18 | export const LOG4JS_NO_COLOUR_DEFAULT_LAYOUT = {
19 | type: 'pattern',
20 | // log4js default pattern %d{yyyy-MM-dd HH:mm:ss:SSS} [%thread] %-5level %logger{36} - %msg%n
21 | // we use process id instead thread id
22 | pattern: '%d{yyyy-MM-dd hh:mm:ss:SSS} %-5.5p --- [%15.15x{name}] %40.40f{3} : %m',
23 | tokens: {
24 | name: (logEvent) => {
25 | return (logEvent.context && logEvent.context['name']) || '-';
26 | }
27 | }
28 | };
29 |
30 | export const LOG4JS_DEFAULT_CONFIG: Configuration = {
31 | appenders: {
32 | stdout: {
33 | type: 'stdout',
34 | layout: LOG4JS_DEFAULT_LAYOUT
35 | },
36 | file: {
37 | type: 'file',
38 | filename: './logs/application.log',
39 | maxLogSize: 20 * 1024 * 1024, // maxLogSize use bytes ad unit
40 | backups: 10, // default use 5 so 1KB file size total rotating
41 | layout: LOG4JS_NO_COLOUR_DEFAULT_LAYOUT
42 | }
43 | },
44 | categories: {
45 | default: {
46 | enableCallStack: true,
47 | appenders: ['stdout', 'file'],
48 | level: 'debug'
49 | }
50 | }
51 | };
52 |
--------------------------------------------------------------------------------
/packages/core/src/log4js.extentions.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc we need upgrade skipIdx=7 so nest module wrapping log4js with 3 more call stack (after tsc)
3 | * -> log4js.classes.ts/js
4 | * -> logger.service.ts/js from @nestjs/common
5 | * -> application usage location
6 | * @see https://github.com/log4js-node/log4js-node/blob/master/lib/logger.js#L10
7 | **/
8 |
9 | const STACK_REG = /at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/;
10 |
11 | export const parseNestModuleCallStack = (data, skipIdx = 7) => {
12 | const stackLines = data.stack.split('\n').slice(skipIdx);
13 | const lineMatch = STACK_REG.exec(stackLines[0]);
14 | if (lineMatch && lineMatch.length === 6) {
15 | return {
16 | functionName: lineMatch[1],
17 | fileName: lineMatch[2],
18 | lineNumber: parseInt(lineMatch[3], 10),
19 | columnNumber: parseInt(lineMatch[4], 10),
20 | callStack: stackLines.join('\n')
21 | };
22 | }
23 | return null;
24 | };
25 |
--------------------------------------------------------------------------------
/packages/core/src/log4js.module.ts:
--------------------------------------------------------------------------------
1 | import { DynamicModule, Global, Module } from '@nestjs/common';
2 | import {
3 | DEFAULT_LOG4JS_OPTIONS,
4 | getLog4jsLoggerToken,
5 | getLog4jsOptionsToken,
6 | Log4jsAsyncOptions,
7 | Log4jsOptions
8 | } from './log4js.options';
9 | import { createAsyncLog4jsOptions, createLog4jsLogger } from './log4js.providers';
10 | import { Log4jsLogger } from './log4js.classes';
11 |
12 | @Global()
13 | @Module({})
14 | export class Log4jsModule {
15 | static forRoot(options: Log4jsOptions = DEFAULT_LOG4JS_OPTIONS): DynamicModule {
16 | return {
17 | module: Log4jsModule,
18 | providers: [
19 | {
20 | provide: getLog4jsOptionsToken(options.name),
21 | useValue: options
22 | },
23 | createLog4jsLogger(options.name),
24 | {
25 | provide: Log4jsLogger,
26 | useExisting: getLog4jsLoggerToken(options.name)
27 | }
28 | ],
29 | exports: [
30 | getLog4jsLoggerToken(options.name),
31 | {
32 | provide: Log4jsLogger,
33 | useExisting: getLog4jsLoggerToken(options.name)
34 | }
35 | ]
36 | };
37 | }
38 |
39 | static forRootAsync(options: Log4jsAsyncOptions): DynamicModule {
40 | return {
41 | module: Log4jsModule,
42 | imports: options.imports,
43 | providers: [
44 | createAsyncLog4jsOptions(options),
45 | createLog4jsLogger(options.name),
46 | {
47 | provide: Log4jsLogger,
48 | useExisting: getLog4jsLoggerToken(options.name)
49 | }
50 | ],
51 | exports: [
52 | getLog4jsLoggerToken(options.name),
53 | {
54 | provide: Log4jsLogger,
55 | useExisting: getLog4jsLoggerToken(options.name)
56 | }
57 | ]
58 | };
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/packages/core/src/log4js.options.ts:
--------------------------------------------------------------------------------
1 | import { Configuration } from 'log4js';
2 | import { FactoryProvider, ModuleMetadata, Type } from '@nestjs/common';
3 | import { LOG4JS_DEFAULT_CONFIG, LOG4JS_LOGGER, LOG4JS_OPTIONS } from './log4js.constants';
4 |
5 | export interface Log4jsOptionsFactory {
6 | createLog4jsOptions(): Log4jsAsyncOptions | Promise;
7 | }
8 |
9 | export interface Log4jsOptions {
10 | name?: string;
11 |
12 | // TODO file url handling + process.env.LOG4JS_CONFIG filepath handling
13 | config?: Configuration;
14 | }
15 |
16 | /**
17 | * @see https://github.com/spring-projects/spring-boot/blob/2.3.x/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/DefaultLogbackConfiguration.java
18 | **/
19 | export const DEFAULT_LOG4JS_OPTIONS: Log4jsOptions = {
20 | config: LOG4JS_DEFAULT_CONFIG
21 | };
22 |
23 | export interface Log4jsAsyncOptions extends Pick {
24 | name?: string;
25 | inject?: FactoryProvider['inject'];
26 | useExisting?: Type;
27 | useClass?: Type;
28 | useFactory?: (...args: any[]) => Log4jsOptions | Promise;
29 | }
30 |
31 | export const isSymbol = (fn: any): fn is symbol => typeof fn === 'symbol';
32 |
33 | export const getLog4jsOptionsToken = (name: string | symbol = LOG4JS_OPTIONS): string | symbol => {
34 | if (name === LOG4JS_OPTIONS) {
35 | return LOG4JS_OPTIONS;
36 | }
37 |
38 | if (!isSymbol(name)) {
39 | return `${name}_LOG4JS_OPTIONS`;
40 | }
41 | };
42 |
43 | export const getLog4jsLoggerToken = (name: string | symbol = LOG4JS_LOGGER): string | symbol => {
44 | if (name === LOG4JS_LOGGER) {
45 | return LOG4JS_LOGGER;
46 | }
47 |
48 | if (!isSymbol(name)) {
49 | return `${name}_LOG4JS_LOGGER`;
50 | }
51 | };
52 |
--------------------------------------------------------------------------------
/packages/core/src/log4js.providers.ts:
--------------------------------------------------------------------------------
1 | import * as log4js from 'log4js';
2 | import { FactoryProvider } from '@nestjs/common';
3 | import {
4 | getLog4jsLoggerToken,
5 | getLog4jsOptionsToken,
6 | Log4jsAsyncOptions,
7 | Log4jsOptions,
8 | Log4jsOptionsFactory
9 | } from './log4js.options';
10 | import { Type } from '@nestjs/common/interfaces/type.interface';
11 | import { Log4jsLogger } from './log4js.classes';
12 | import { parseNestModuleCallStack } from './log4js.extentions';
13 |
14 | export type Log4jsLoggerFactoryProvider = FactoryProvider>;
15 | export type Log4jsOptionsFactoryProvider = FactoryProvider>;
16 |
17 | export const createLog4jsLogger = (name: string): Log4jsLoggerFactoryProvider => ({
18 | provide: getLog4jsLoggerToken(name),
19 | inject: [getLog4jsOptionsToken(name)],
20 | useFactory: async (options: Log4jsOptions): Promise => {
21 | const config = options.config;
22 | const logger = log4js.configure(config).getLogger();
23 |
24 | logger.setParseCallStackFunction(parseNestModuleCallStack);
25 |
26 | // TODO: add log4js instance container so we can get different logger instance
27 | return new Log4jsLogger(logger);
28 | }
29 | });
30 |
31 | export const createAsyncLog4jsOptions = (options: Log4jsAsyncOptions): Log4jsOptionsFactoryProvider => {
32 | if (options.useFactory) {
33 | return {
34 | provide: getLog4jsOptionsToken(options.name),
35 | inject: options.inject,
36 | useFactory: options.useFactory
37 | };
38 | }
39 |
40 | const inject = [(options.useClass || options.useExisting) as Type];
41 |
42 | return {
43 | provide: getLog4jsOptionsToken(options.name),
44 | inject: inject,
45 | useFactory: async (log4jsOptionsFactory: Log4jsOptionsFactory) => {
46 | return log4jsOptionsFactory.createLog4jsOptions();
47 | }
48 | };
49 | };
50 |
--------------------------------------------------------------------------------
/packages/core/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "declaration": true,
6 | "removeComments": true,
7 | "noLib": false,
8 | "emitDecoratorMetadata": true,
9 | "resolveJsonModule": true,
10 | "experimentalDecorators": true,
11 | "noImplicitAny": false,
12 | "sourceMap": false,
13 | "outDir": "./dist",
14 | "rootDir": "./src",
15 | "skipLibCheck": true
16 | },
17 | "include": [
18 | "src/**/*"
19 | ],
20 | "exclude": [
21 | "node_modules",
22 | "src/__tests__",
23 | "**/*.spec.ts",
24 | "**/*.test.ts"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "declaration": true,
6 | "removeComments": true,
7 | "noLib": false,
8 | "emitDecoratorMetadata": true,
9 | "resolveJsonModule": true,
10 | "experimentalDecorators": true,
11 | "noImplicitAny": false,
12 | "sourceMap": false,
13 | "skipLibCheck": true
14 | },
15 | "include": [
16 | "src/**/*"
17 | ],
18 | "exclude": [
19 | "node_modules",
20 | "**/*.spec.ts",
21 | "**/*.test.ts"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------