Completed
Push — master ( f2a0af...598926 )
by Fike
39s
created

lib/logger/slf4j.js   B

Complexity

Total Complexity 39
Complexity/F 1.5

Size

Lines of Code 262
Function Count 26

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 0
nc 48
dl 0
loc 262
rs 8.2857
c 3
b 0
f 0
wmc 39
mnd 1
bc 36
fnc 26
bpm 1.3846
cpm 1.5
noi 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
A Object.forEach 0 3 1
B slf4j.js ➔ Slf4j 0 138 4
A Slf4j.Context 0 19 1
A Slf4j.factory 0 14 3
1
/**
2
 * @module logger/slf4j
3
 */
4
5
var C = require('./_common')
6
var Level = C.Level
7
var Threshold = C.Threshold
8
var levelOf = C.level
9
var toThreshold = C.threshold
10
var Context = C.Context
11
12
/**
13
 * @class Slf4j
14
 *
15
 * @param {string} [name] Logger name.
16
 * @param {Context} [context] Logger context.
17
 *
18
 * @implements IVarArgLogger
19
 */
20
function Slf4j (name, context) {
21
  if (!context) {
22
    context = DefaultContext
23
  }
24
  // backward compatibility for 0.1.x/0.2.x
25
  if (!(context instanceof Context)) {
26
    context = new Slf4j.Context(context, arguments[2])
27
  }
28
  var mdc = {}
29
30
  function substitute (pattern, substitutions) {
31
    var e = substitutions.filter(function (s) { return s instanceof Error })
32
    var o = substitutions.filter(function (s) { return !(s instanceof Error) })
33
    var s = o.reduce(function (carrier, s) {
34
      return carrier.replace('{}', render(s))
35
    }, pattern)
36
37
    return e.reduce(function (carrier, e) {
38
      return carrier + '\n' + renderException(e)
39
    }, s)
40
  }
41
42
  function renderException (e) {
43
    return e.name + ': ' + e.message + '\nStack:\n' + e.stack
44
  }
45
46
  function render (v) {
47
    v = typeof v === 'undefined' ? '{undefined}' : v
48
    // noinspection EqualityComparisonWithCoercionJS
49
    return v != null && v.constructor === String ? v : JSON.stringify(v)
50
  }
51
52
  function log (level, pattern) {
53
    level = levelOf(level)
54
    if (toThreshold(level) < toThreshold(context.getLevel(name))) {
55
      return
56
    }
57
    var prefix = '[' + level.toUpperCase() + ']'
58
    if (name) {
59
      prefix += ' ' + name
60
    }
61
    var mdcPrefix = Object.keys(mdc).map(function (key) {
62
      return key + '=' + render(mdc[key])
63
    }).join(', ')
64
    if (mdcPrefix) {
65
      prefix += ' [' + mdcPrefix + ']'
66
    }
67
    var subs = [].slice.call(arguments, 2)
68
    context.getWriter(name).write(substitute(prefix + ': ' + pattern, subs))
69
  }
70
71
  // noinspection JSUnusedGlobalSymbols
72
  this.log = log
73
74
  for (var i = Threshold.TRACE; i <= Threshold.ERROR; i++) {
75
    this[levelOf(i).toLowerCase()] = (function (self, threshold) {
76
      return function () {
77
        log.apply(null, ([threshold].concat([].slice.call(arguments))))
78
      }
79
    })(this, i)
80
  }
81
82
  this.getName = function () { return name }
83
84
  this.setWriter = function (writer) {
85
    context.setWriter(name, writer)
86
    return this
87
  }
88
89
  this.getWriter = function () { return context.getWriter(name) }
90
91
  this.setLevel = function (level) {
92
    context.setLevel(name, level)
93
    return this
94
  }
95
96
  this.getLevel = function () { return context.getLevel(name) }
97
98
  /**
99
   * @deprecated
100
   */
101
  this.setThreshold = this.setLevel
102
103
  /**
104
   * @deprecated
105
   */
106
  this.getThreshold = this.getLevel
107
108
  this.getContext = function () { return context }
109
110
  this.attach = function (name, value) { mdc[name] = value }
111
112
  this.detach = function (name) { delete mdc[name] }
113
114
  this.attachAll = function (values) { mdc = values }
115
116
  this.detachAll = function () {
117
    var b = mdc
118
    mdc = {}
119
    return b
120
  }
121
122
  /**
123
   * @function Slf4j#trace
124
   * @param {string} pattern Logging pattern with `{}` as a place for substitution
125
   * @param {...object} parameters List of pattern parameters
126
   */
127
128
  /**
129
   * @function Slf4j#debug
130
   * @param {string} pattern Logging pattern with `{}` as a place for substitution
131
   * @param {...object} parameters List of pattern parameters
132
   */
133
134
  /**
135
   * @function Slf4j#notice
136
   * @param {string} pattern Logging pattern with `{}` as a place for substitution
137
   * @param {...object} parameters List of pattern parameters
138
   */
139
140
  /**
141
   * @function Slf4j#info
142
   * @param {string} pattern Logging pattern with `{}` as a place for substitution
143
   * @param {...object} parameters List of pattern parameters
144
   */
145
146
  /**
147
   * @function Slf4j#warn
148
   * @param {string} pattern Logging pattern with `{}` as a place for substitution
149
   * @param {...object} parameters List of pattern parameters
150
   */
151
152
  /**
153
   * @function Slf4j#error
154
   * @param {string} pattern Logging pattern with `{}` as a place for substitution
155
   * @param {...object} parameters List of pattern parameters
156
   */
157
}
158
159
/**
160
 * @class
161
 * @extends {Context.<Slf4j>}
162
 */
163
Slf4j.Context = function () {
164
  Context.apply(this, arguments)
165
  var self = this
166
  /**
167
   * @param {string} name
168
   * @param {Level} [threshold]
169
   * @param {IWritable} [writer]
170
   * @return {Slf4j}
171
   */
172
  this.create = function (name, threshold, writer) {
173
    if (threshold) {
174
      self.setLevel(name, threshold)
175
    }
176
    if (writer) {
177
      self.setWriter(name, writer)
178
    }
179
    return new Slf4j(name, self)
180
  }
181
}
182
Slf4j.Context.prototype = Object.create(Context.prototype)
183
Slf4j.Context.constructor = Slf4j.Context
184
185
var DefaultContext = new Slf4j.Context()
186
187
/**
188
 * @function Slf4j.create
189
 * @param {string} name
190
 * @param {Level} [level]
191
 * @param {IWritable} [writer]
192
 * @return {Slf4j}
193
 */
194
195
/**
196
 * @function Slf4j.getWriter
197
 * @param {string} name
198
 * @return {IWritable}
199
 */
200
201
/**
202
 * @function Slf4j.setWriter
203
 * @param {string} name
204
 * @param {IWritable} writer
205
 * @return {ILoggerContext.<Slf4j>}
206
 */
207
208
/**
209
 * @function Slf4j.getLevel
210
 * @param {string} name
211
 * @return {Level}
212
 */
213
214
/**
215
 * @function Slf4j.setLevel
216
 * @param {string} name
217
 * @param {Level} level
218
 * @return {ILoggerContext.<Slf4j>}
219
 */
220
221
/**
222
 * @deprecated
223
 * @function Slf4j.getThreshold
224
 * @param {string} name
225
 * @return {Level}
226
 */
227
228
/**
229
 * @deprecated
230
 * @function Slf4j.setThreshold
231
 * @param {string} name
232
 * @param {Level} level
233
 * @return {ILoggerContext.<Slf4j>}
234
 */
235
Object.keys(DefaultContext).forEach(function (method) {
236
  Slf4j[method] = DefaultContext[method].bind(DefaultContext)
237
})
238
239
/**
240
 * @param {LoggerOptions} [options]
241
 * @param {String} [name] Default name to use in case options don't include it
242
 * @param {Context} [context] Default context
243
 * @param {Level} [level] Default logging level
244
 * @return {IVarArgLogger}
245
 */
246
Slf4j.factory = function (options, name, context, level) {
247
  options = options || {}
248
  if (typeof options.log === 'function') {
249
    // then instance of logger have been passed
250
    return options
251
  }
252
  if (options.instance) {
253
    return options.instance
254
  }
255
  context = options.context || context || Slf4j
256
  var logger = context.create(options.name || name, level || options.level)
257
  logger.attachAll(options.mdc || {})
258
  return logger
259
}
260
261
module.exports = {
262
  Slf4j: Slf4j,
263
  /** @deprecated */
264
  Context: Slf4j.Context,
265
  Level: Level
266
}
267