@creejs/commons-logging 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js ADDED
@@ -0,0 +1,257 @@
1
+ 'use strict'
2
+ /**
3
+ * @module CommonsLogging
4
+ * @description Common logging library
5
+ *
6
+ * Follow the sequence to init log system: addProvider() -> use() -> configure() -> getLogger()
7
+ * 1. Add ability to handle the type of library
8
+ * * eg. after adding Log4jsProvider, we can use Log4js library
9
+ * 2. But we MAY NOT use it now.
10
+ * * call useProvider(typeName) to select which kind of LogProvider Implementation to use.
11
+ * * call configure(typeName, nativeLib, setting) to LogProvider Implementation
12
+ */
13
+ // 3rd
14
+ // internal
15
+ const {
16
+ TypeAssert: { assertNotNil, assertString },
17
+ TypeUtils: { isFunction, isNil }
18
+ } = require('@creejs/commons-lang')
19
+
20
+ // owned
21
+ const LogFactory = require('./log-factory')
22
+ const Logger = require('./logger')
23
+ const ProviderType = require('./provider-type')
24
+ const LogLevel = require('./log-level')
25
+ const LogConfig = require('./log-config')
26
+
27
+ const ConsoleProvider = require('./console')
28
+ const Log4jsProvider = require('./log4js')
29
+ const Provider = require('./provider')
30
+
31
+ // module vars
32
+
33
+ /**
34
+ * Store Created Loggers, indexed with Names
35
+ * @type {Map<string, Logger>}
36
+ * @private
37
+ */
38
+ const name2Logger = new Map()
39
+
40
+ /**
41
+ * set Global logging level
42
+ * @param {'TRACE'|'DEBUG'|'INFO'|'WARN'|'ERROR'|'FATAL'|'OFF'|'trace'|'debug'|'info'|'warn'|'error'|'fatal'|'off'} level - The log level
43
+ */
44
+ function setLevel (level) {
45
+ assertString(level)
46
+ const upperLevel = level.toUpperCase()
47
+ const levelNumber = LogLevel.name2Value(upperLevel)
48
+ if (levelNumber == null) {
49
+ throw new Error(`Invalid log level: ${level}`)
50
+ }
51
+ if (levelNumber === LogConfig.currentLevel) {
52
+ return // no change
53
+ }
54
+ LogConfig.currentLevel = levelNumber
55
+
56
+ // refresh existed factories
57
+ for (const [, factory] of LogConfig.listFactories()) {
58
+ factory.setLevel(levelNumber)
59
+ }
60
+ // refresh existed Loggers
61
+ for (const logger of name2Logger.values()) {
62
+ if (logger.level !== levelNumber) {
63
+ logger.setLevel(levelNumber)
64
+ }
65
+ }
66
+ }
67
+
68
+ function currentProvider () {
69
+ return LogConfig.currentProvider
70
+ }
71
+
72
+ /**
73
+ * Set the provider using currently
74
+ * @param {string} typeName - The type name of the logging provider to use.
75
+ * @returns {void}
76
+ * @throws {Error} If the provider name is unknown.
77
+ */
78
+ function useProvider (typeName) {
79
+ assertString(typeName)
80
+ typeName = typeName.toUpperCase()
81
+ const provider = LogConfig.getProvider(typeName)
82
+ if (provider == null) {
83
+ throw new Error(`No Provider Named with: ${typeName}`)
84
+ }
85
+ LogConfig.currentProvider = typeName
86
+ }
87
+
88
+ /**
89
+ * Removes and returns the provider associated with the given type name.
90
+ * If no provider exists for the type name, the function returns undefined.
91
+ *
92
+ * @param {string} typeName - The type name of the provider to remove.
93
+ * @returns {boolean} The removed provider, or undefined if not found.
94
+ */
95
+ function removeProvider (typeName) {
96
+ if (typeName == null) {
97
+ return false
98
+ }
99
+ assertString(typeName)
100
+ typeName = typeName.toUpperCase()
101
+ return LogConfig.removeProvider(typeName)
102
+ }
103
+
104
+ /**
105
+ * Add a type of Provider
106
+ *
107
+ * More:
108
+ * 1. A Provider is a Module
109
+ * 2. The module must include the following functions:
110
+ * 1. getType() - Returns the type name of the provider.
111
+ * 2. createLogFactory() - Creates a new LogFactory instance.
112
+ * @param {Provider} provider - Logging Library Module
113
+ * @returns {void}
114
+ */
115
+ function addProvider (provider) {
116
+ assertNotNil(provider)
117
+ const { getType, createLogFactory } = provider
118
+ if (!isFunction(getType) || !isFunction(createLogFactory)) {
119
+ throw new Error('Invalid Provider Module, missing getType(), createLogFactory() functions')
120
+ }
121
+ let typeName = provider.getType()
122
+ assertString(typeName)
123
+ typeName = typeName.toUpperCase()
124
+ LogConfig.addProvider(typeName, provider)
125
+ // set current provider if not set yet
126
+ if (isNil(currentProvider())) {
127
+ useProvider(typeName)
128
+ }
129
+ }
130
+
131
+ function clearProviders () {
132
+ name2Logger.clear()
133
+ LogConfig.clear()
134
+ }
135
+
136
+ /**
137
+ * configure provider to initialize its LogFactory
138
+ * 1. find the LogProvider Implementation of "typeName"
139
+ * * if type is not supported, throw error
140
+ * 2. use the nativeLib and setting to initialize the LogProvider
141
+ * 3. create a LogFactory via teh LogProvider
142
+ * @param {string} typeName - The type of logging provider to configure.
143
+ * @param {*} [nativeLib] - The native library to use for logging.
144
+ * @param {*} [setting] - Configuration settings for the logging provider.
145
+ * @throws {Error} If the typeName is not recognized.
146
+ */
147
+ function configureProvider (typeName, nativeLib, setting) {
148
+ assertString(typeName)
149
+ typeName = typeName.toUpperCase()
150
+ const provider = LogConfig.getProvider(typeName)
151
+ if (provider == null) {
152
+ throw new Error(`No Provider: ${typeName}`)
153
+ }
154
+ const factory = provider.createLogFactory(nativeLib, setting)
155
+ LogConfig.addFactory(typeName, factory)
156
+ }
157
+
158
+ /**
159
+ * Configures and immediately uses a logging provider with the given settings.
160
+ * @param {string} typeName - The type/name identifier for the provider.
161
+ * @param {*} nativeLib - The native library implementation to configure.
162
+ * @param {*} setting - Configuration settings for the provider.
163
+ */
164
+ function configureThenUseProvider (typeName, nativeLib, setting) {
165
+ configureProvider(typeName, nativeLib, setting)
166
+ useProvider(typeName)
167
+ }
168
+
169
+ /**
170
+ * Gets a logger instance for the specified logger name using the current provider.
171
+ * @param {string} loggerName - The name of the logger to retrieve.
172
+ * @returns {Logger} The logger instance.
173
+ * @throws {Error} If no default provider is set or if the current provider is not initialized.
174
+ */
175
+ function getLogger (loggerName) {
176
+ // if logger already exists, return it
177
+ let logger = name2Logger.get(loggerName)
178
+ if (logger != null) {
179
+ return logger
180
+ }
181
+ // create a new logger via the current provider's LogFactory
182
+ const currentTypeName = currentProvider()
183
+ if (currentTypeName == null) {
184
+ throw new Error('No Default LogProvider, call useProvider(typeName)')
185
+ }
186
+ const factory = LogConfig.getFactory(currentTypeName)
187
+ if (factory == null) {
188
+ throw new Error('configureProvider(typeName, nativeLib, settting) before getting logger via Provider')
189
+ }
190
+ logger = factory.createLogger(loggerName)
191
+ name2Logger.set(loggerName, logger)
192
+ return logger
193
+ }
194
+
195
+ function initLogSystem () {
196
+ addProvider(Log4jsProvider)
197
+ // ConsoleProvider as default impl
198
+ addProvider(ConsoleProvider)
199
+ configureProvider(ProviderType.Console, console)
200
+ useProvider(ProviderType.Console) // Use ConsoleLogger as default
201
+ }
202
+
203
+ initLogSystem()
204
+
205
+ const CommonsLogging = {
206
+ Provider,
207
+ LogFactory,
208
+ Logger,
209
+ LogLevel,
210
+ ProviderType,
211
+ getLogger,
212
+ setLevel,
213
+ useProvider,
214
+ /**
215
+ * alias for {@link CommonsLogging.useProvider}
216
+ * @see {@link CommonsLogging.useProvider}
217
+ * @function
218
+ * @alias module:CommonsLogging.use
219
+ */
220
+ use: useProvider,
221
+ configureProvider,
222
+ /**
223
+ * @function
224
+ * @alias module:CommonsLogging.confiure
225
+ */
226
+ configure: configureProvider,
227
+ configureThenUseProvider,
228
+ /**
229
+ * @function
230
+ * @alias module:CommonsLogging.configureThenUseProvider
231
+ */
232
+ configureThenUse: configureThenUseProvider,
233
+ addProvider,
234
+ add: addProvider,
235
+ clearProviders,
236
+ currentProvider,
237
+ /**
238
+ * @function
239
+ * @alias module:CommonsLogging.current
240
+ */
241
+ current: currentProvider,
242
+ removeProvider,
243
+ /**
244
+ * @function
245
+ * @alias module:CommonsLogging.remove
246
+ */
247
+ remove: removeProvider,
248
+ /**
249
+ * @alias module:CommonsLogging.ConsoleProvider
250
+ */
251
+ ConsoleProvider,
252
+ /**
253
+ * @alias module:CommonsLogging.Log4jsProvider
254
+ */
255
+ Log4jsProvider
256
+ }
257
+ module.exports = CommonsLogging
@@ -0,0 +1,157 @@
1
+ 'use strict'
2
+ // internal
3
+ const { TypeAssert: { assertString } } = require('@creejs/commons-lang')
4
+ // owned
5
+ const { DefaultLevel } = require('./log-level')
6
+ // eslint-disable-next-line no-unused-vars
7
+ const LogFactory = require('./log-factory')
8
+ const Provider = require('./provider')
9
+ /**
10
+ * type name of current provider
11
+ * @type {string}
12
+ * @public
13
+ */
14
+ // @ts-ignore
15
+ // eslint-disable-next-line prefer-const
16
+ let currentProvider = null
17
+
18
+ /**
19
+ * Global logging level
20
+ * @type {number}
21
+ * @public
22
+ */
23
+ // @ts-ignore
24
+ // eslint-disable-next-line prefer-const
25
+ let currentLevel = DefaultLevel
26
+
27
+ /**
28
+ * The map of registered logging libraries
29
+ * @type {Map<string,Provider>}
30
+ * @private
31
+ */
32
+ const type2Provider = new Map()
33
+
34
+ /**
35
+ * Adds a logging provider for the specified type.
36
+ * @param {string} typeName - The type identifier for the provider.
37
+ * @param {Provider} provider - The logging provider implementation.
38
+ * @returns {void}
39
+ */
40
+ function addProvider (typeName, provider) {
41
+ assertString(typeName)
42
+ Provider.assertProviderLike(provider)
43
+ type2Provider.set(typeName, provider)
44
+ }
45
+
46
+ /**
47
+ * Gets the logging provider for the specified type name.
48
+ * @param {string} typeName - The type name to look up in the provider map.
49
+ * @returns {Provider|undefined} The logging provider instance if found, otherwise undefined.
50
+ */
51
+ function getProvider (typeName) {
52
+ assertString(typeName)
53
+ return type2Provider.get(typeName)
54
+ }
55
+
56
+ /**
57
+ * Removes a logging provider of the specified type.
58
+ * @param {string} typeName - The type name of the provider to remove.
59
+ * @returns {boolean}
60
+ */
61
+ function removeProvider (typeName) {
62
+ assertString(typeName)
63
+ return type2Provider.delete(typeName)
64
+ }
65
+
66
+ function clearProviders () {
67
+ type2Provider.clear()
68
+ }
69
+
70
+ /**
71
+ * Returns an array of all registered factory types and intances.
72
+ * 1. Each entry is a [type, factory] pair
73
+ * @returns {Array<[string, Provider]>} An array of factory entries.
74
+ */
75
+ function listProviders () {
76
+ return [...type2Provider.entries()]
77
+ }
78
+
79
+ /**
80
+ * Created LogFactories Index with type name
81
+ * @type {Map<string, LogFactory>}
82
+ * @public
83
+ */
84
+ const type2Factory = new Map()
85
+
86
+ /**
87
+ * Registers a log factory for a given type name.
88
+ * @param {string} typeName - The name of the log type to register.
89
+ * @param {LogFactory} logFactory - Factory function that creates a logger for the specified type.
90
+ */
91
+ function addFactory (typeName, logFactory) {
92
+ assertString(typeName)
93
+ LogFactory.assertLogFactoryLike(logFactory)
94
+ type2Factory.set(typeName, logFactory)
95
+ }
96
+
97
+ /**
98
+ * Removes a factory of the given type from the type-to-factory mapping.
99
+ * @param {string} typeName - The name of the type whose factory should be removed.
100
+ * @returns {boolean}
101
+ */
102
+ function removeFactory (typeName) {
103
+ assertString(typeName)
104
+ return type2Factory.delete(typeName)
105
+ }
106
+
107
+ /**
108
+ * Gets the factory function associated with the given type name.
109
+ * @param {string} typeName - The name of the type to look up.
110
+ * @returns {LogFactory|undefined} The factory function for the specified type.
111
+ */
112
+ function getFactory (typeName) {
113
+ assertString(typeName)
114
+ return type2Factory.get(typeName)
115
+ }
116
+
117
+ /**
118
+ * Clears all registered factories from the type2Factory instance.
119
+ * This is typically used to reset the factory state during testing or teardown.
120
+ */
121
+ function clearFactories () {
122
+ type2Factory.clear()
123
+ }
124
+
125
+ /**
126
+ * Returns an array of all registered factory types and intances.
127
+ * 1. Each entry is a [type, factory] pair
128
+ * @returns {Array<[string, LogFactory]>} An array of factory entries.
129
+ */
130
+ function listFactories () {
131
+ return [...type2Factory.entries()]
132
+ }
133
+
134
+ function clear () {
135
+ clearProviders()
136
+ clearFactories()
137
+ }
138
+
139
+ const LogConfig = {
140
+ currentProvider,
141
+ currentLevel,
142
+ type2Provider,
143
+ type2Factory,
144
+ addProvider,
145
+ getProvider,
146
+ removeProvider,
147
+ clearProviders,
148
+ listProviders,
149
+ addFactory,
150
+ getFactory,
151
+ removeFactory,
152
+ clearFactories,
153
+ listFactories,
154
+ clear
155
+ }
156
+
157
+ module.exports = LogConfig
@@ -0,0 +1,88 @@
1
+ 'use strict'
2
+
3
+ // owned
4
+ // eslint-disable-next-line no-unused-vars
5
+ const Logger = require('./logger')
6
+
7
+ /**
8
+ * @abstract
9
+ */
10
+ class LogFactory {
11
+ /**
12
+ * Checks if a value resembles a LogFactory by verifying it has required methods.
13
+ * @param {*} value - The value to check
14
+ * @returns {boolean}
15
+ */
16
+ static isLogFactoryLike (value) {
17
+ if (value == null) {
18
+ return false
19
+ }
20
+ return typeof value === 'object' && typeof value.createLogger === 'function' && typeof value.setLevel === 'function'
21
+ }
22
+
23
+ /**
24
+ * Asserts that the given value is a valid LogFactory-Like object.
25
+ * @throws {Error} Throws an error if the value is not LogFactory-Like
26
+ * @param {*} value - The value to check.
27
+ */
28
+ static assertLogFactoryLike (value) {
29
+ if (!this.isLogFactoryLike(value)) {
30
+ throw new Error('Not LogFactory')
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Creates a new logging provider instance.
36
+ * @param {{}} libraryModule - the library module
37
+ * @param {{}} setting - Configuration settings for the provider
38
+ */
39
+ constructor (libraryModule, setting) {
40
+ this._libraryModule = libraryModule
41
+ this._setting = setting
42
+ }
43
+
44
+ get libraryModule () {
45
+ return this._libraryModule
46
+ }
47
+
48
+ get setting () {
49
+ return this._setting
50
+ }
51
+
52
+ /**
53
+ * Initializes the logging provider.
54
+ * 1. Do nothing in the default implementation.
55
+ * 2. Override this method to initialize the provider.
56
+ * @returns {Promise<void>|void}
57
+ */
58
+ init () {
59
+ // do nothing
60
+ }
61
+
62
+ /**
63
+ * Update factory's Log Level
64
+ * 1. Only Provider knows how to update
65
+ * * update level in "setting", so the new created Logger will use the new level
66
+ * 2. called when users want to change global log level via CommonsLogging.setLevel()
67
+ * @param {number} level - The log level to set, see {@link LogLevel.Level}
68
+ * @returns {void}
69
+ * @throws {Error} Throws an error as this method is Not Impled Yet.
70
+ * @abstract
71
+ */
72
+ setLevel (level) {
73
+ throw new Error('Not Impled Yet')
74
+ }
75
+
76
+ /**
77
+ * Creates a new logger named with the "loggerName"
78
+ * @param {string} loggerName - The name to associate with the logger instance.
79
+ * @throws {Error} Throws an error indicating the method is Not Impled Yet yet.
80
+ * @returns {Logger} A new logger intance
81
+ * @abstract
82
+ */
83
+ createLogger (loggerName) {
84
+ throw new Error('Not Impled Yet')
85
+ }
86
+ }
87
+
88
+ module.exports = LogFactory
@@ -0,0 +1,163 @@
1
+ 'use strict'
2
+
3
+ const { TypeUtils: { isNumber, isString } } = require('@creejs/commons-lang')
4
+
5
+ /**
6
+ * @namespace LogLevel
7
+ * @description Defines the logging levels and provides utilities for working with them.
8
+ */
9
+ // module vars
10
+ const TRACE = 'TRACE'
11
+ const DEBUG = 'DEBUG'
12
+ const INFO = 'INFO'
13
+ const WARN = 'WARN'
14
+ const ERROR = 'ERROR'
15
+ const FATAL = 'FATAL'
16
+ const OFF = 'OFF'
17
+ const ALL = 'ALL'
18
+
19
+ const Names = new Set([TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF, ALL])
20
+ /**
21
+ * The logging level numbers, where OFF=-1, FATAL=0, ERROR=1, WARN=2, INFO=3, DEBUG=4, TRACE=5, ALL=6
22
+ * @enum {number}
23
+ * @memberof LogLevel
24
+ * @static
25
+ */
26
+ const Level = {
27
+ OFF: -1,
28
+ FATAL: 0,
29
+ ERROR: 1,
30
+ WARN: 2,
31
+ INFO: 3,
32
+ DEBUG: 4,
33
+ TRACE: 5,
34
+ ALL: 6
35
+ }
36
+
37
+ /**
38
+ * Standard logging level names
39
+ * @enum {string}
40
+ * @memberof LogLevel
41
+ * @static
42
+ * @constant
43
+ */
44
+ const Name = {
45
+ TRACE,
46
+ DEBUG,
47
+ INFO,
48
+ WARN,
49
+ ERROR,
50
+ FATAL,
51
+ OFF
52
+ }
53
+
54
+ /**
55
+ * Internal map for quick lookup of level names by their numeric values
56
+ * @type {Map<number, string>}
57
+ * @private
58
+ */
59
+ const Value2Name = new Map()
60
+ for (const [name, value] of Object.entries(Level)) {
61
+ Value2Name.set(value, name)
62
+ }
63
+
64
+ /**
65
+ * The default logging level (ERROR)
66
+ * @type {number}
67
+ * @memberof LogLevel
68
+ * @static
69
+ */
70
+ const DefaultLevel = Level.ERROR
71
+
72
+ /**
73
+ * Converts a numeric logging level value to its corresponding name.
74
+ * @param {number} value - The numeric logging level value to convert.
75
+ * @returns {string|undefined} The name associated with the given logging level value, from {@link LogLevel.Name}.
76
+ * @memberof LogLevel
77
+ * @static
78
+ */
79
+ function value2Name (value) {
80
+ if (!isNumber(value)) {
81
+ return undefined
82
+ }
83
+ return Value2Name.get(value)
84
+ }
85
+
86
+ /**
87
+ * Converts a logging level name to its corresponding numeric value.
88
+ * @param {string} name - The name of the logging level.
89
+ * @returns {number|undefined} The numeric value of the logging level from {@link LogLevel.Level}, or undefined if name is not supported.
90
+ * @memberof LogLevel
91
+ * @static
92
+ */
93
+ function name2Value (name) {
94
+ if (!isString(name)) {
95
+ return undefined
96
+ }
97
+ // @ts-ignore
98
+ return Level[name.toUpperCase()]
99
+ }
100
+
101
+ /**
102
+ * Checks if the given level is a valid log level.
103
+ * @param {number} level - The log level to check.
104
+ * @returns {boolean} True if the level is valid, false otherwise.
105
+ */
106
+ function hasLevel (level) {
107
+ return Value2Name.has(level)
108
+ }
109
+
110
+ /**
111
+ * Checks if the given level name exists in the Name enum/object.
112
+ * @param {string} levelName - The name of the log level to check.
113
+ * @returns {boolean} True if the level name exists, false otherwise.
114
+ */
115
+ function hasName (levelName) {
116
+ if (!isString(levelName)) {
117
+ return false
118
+ }
119
+ return Names.has(levelName.toUpperCase())
120
+ }
121
+
122
+ /**
123
+ * Validates that a given level is a number and falls within the valid range.
124
+ * @param {*} level - The log level to validate
125
+ * @throws {Error} If level is not a number or outside valid range (Level.OFF to Level.ALL)
126
+ */
127
+ function assertLevel (level) {
128
+ if (!isNumber(level)) {
129
+ throw new Error(`Level Not Number: type=${typeof level} value=${level}`)
130
+ }
131
+ if (level < Level.OFF || level > Level.ALL) {
132
+ throw new Error(`Not Valid Level: ${level}, Expect between ${Level.OFF} and ${Level.ALL}`)
133
+ }
134
+ }
135
+
136
+ const LogLevel = {
137
+ Name,
138
+ Level,
139
+ DefaultLevel,
140
+ hasLevel,
141
+ hasName,
142
+ assertLevel,
143
+ /**
144
+ * Same with [Name]{@link LogLevel.Name}
145
+ * @type {Object}
146
+ * @memberof LogLevel
147
+ * @static
148
+ */
149
+ LevelName: Name,
150
+ /**
151
+ * Same with [Level]{@link LogLevel.Level}
152
+ * @type {Object}
153
+ * @memberof LogLevel
154
+ * @static
155
+ */
156
+ LevelValue: Level,
157
+
158
+ value2Name,
159
+
160
+ name2Value
161
+ }
162
+
163
+ module.exports = LogLevel
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ // internal
4
+
5
+ // owned
6
+ const Log4jsProvider = require('./log4js-provider')
7
+
8
+ // module vars
9
+ const log4jsProvider = new Log4jsProvider()
10
+
11
+ module.exports = log4jsProvider
@@ -0,0 +1,12 @@
1
+ 'use strict'
2
+
3
+ const DefaultConfig = { // 6x fromat
4
+ appenders: {
5
+ out: { type: 'console' }
6
+ },
7
+ categories: {
8
+ default: { appenders: ['out'], level: 'error' }
9
+ }
10
+ }
11
+
12
+ module.exports = DefaultConfig