Skip to content

Commit e99493d

Browse files
BKNDLSS-32283 Implement LogLevels in the JS-SDK (#239)
1 parent 2a7a986 commit e99493d

File tree

5 files changed

+150
-7
lines changed

5 files changed

+150
-7
lines changed

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,11 @@ class Backendless {
146146

147147
app.__removeService('LocalCache')
148148

149+
const loggingConfig = Object.assign({ loadLevels: true, defaultLevel: 'all', levels: {} }, config.logging)
150+
149151
if (app.__hasService('Logging')) {
150152
app.Logging.reset()
153+
app.Logging.setConfig(loggingConfig)
151154
}
152155

153156
if (app.__hasService('Users')) {
@@ -156,6 +159,8 @@ class Backendless {
156159

157160
delete this.__device
158161

162+
app.loggingConfig = loggingConfig
163+
159164
return app
160165
}
161166

src/logging/index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ export default class Logging {
66
this.app = app
77

88
this.reset()
9+
10+
this.setConfig(app.loggingConfig)
11+
}
12+
13+
setConfig(config) {
14+
this.config = config
15+
16+
if (config.loadLevels) {
17+
this.loadLoggingLevels()
18+
}
919
}
1020

1121
reset() {
@@ -16,6 +26,20 @@ export default class Logging {
1626
this.messagesLimit = 100
1727
}
1828

29+
loadLoggingLevels() {
30+
this.app.request
31+
.get({ url: this.app.urls.loggingLevels() })
32+
.then(loggers => {
33+
loggers.forEach(logger => {
34+
this.config.levels[logger.name] = logger.level
35+
})
36+
})
37+
.catch(error => {
38+
// eslint-disable-next-line no-console
39+
console.error('Could not load logging levels: ', error)
40+
})
41+
}
42+
1943
getLogger(loggerName) {
2044
if (!loggerName || typeof loggerName !== 'string') {
2145
throw new Error('Logger Name must be provided and must be a string.')

src/logging/logger.js

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
const LogLevelPriorities = {
2+
off : 0,
3+
fatal: 1,
4+
error: 2,
5+
warn : 3,
6+
info : 4,
7+
debug: 5,
8+
trace: 6,
9+
all : 6,
10+
}
11+
112
export default class Logger {
213

314
constructor(name, logging) {
@@ -6,26 +17,44 @@ export default class Logger {
617
}
718

819
debug(message) {
9-
return this.logging.push(this.name, 'DEBUG', message)
20+
return this.log('DEBUG', message)
1021
}
1122

1223
info(message) {
13-
return this.logging.push(this.name, 'INFO', message)
24+
return this.log('INFO', message)
1425
}
1526

1627
warn(message, exception) {
17-
return this.logging.push(this.name, 'WARN', message, exception)
28+
return this.log('WARN', message, exception)
1829
}
1930

2031
error(message, exception) {
21-
return this.logging.push(this.name, 'ERROR', message, exception)
32+
return this.log('ERROR', message, exception)
2233
}
2334

2435
fatal(message, exception) {
25-
return this.logging.push(this.name, 'FATAL', message, exception)
36+
return this.log('FATAL', message, exception)
2637
}
2738

2839
trace(message) {
29-
return this.logging.push(this.name, 'TRACE', message)
40+
return this.log('TRACE', message)
41+
}
42+
43+
log(level, message, exception) {
44+
if (this.min(level)) {
45+
return this.logging.push(this.name, level, message, exception)
46+
}
47+
}
48+
49+
min(level) {
50+
const configuredLevel = this.logging.config.levels[this.name]
51+
52+
if (!configuredLevel) {
53+
const { defaultLevel } = this.logging.config
54+
55+
return LogLevelPriorities[defaultLevel.toLowerCase()] >= LogLevelPriorities[level.toLowerCase()]
56+
}
57+
58+
return LogLevelPriorities[configuredLevel.toLowerCase()] >= LogLevelPriorities[level.toLowerCase()]
3059
}
3160
}

src/urls.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export default class Urls {
2727
return `${this.root()}/log`
2828
}
2929

30+
loggingLevels() {
31+
return `${this.logging()}/logger`
32+
}
33+
3034
//cache
3135

3236
cache() {

test/unit/specs/logging.js

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from 'chai'
22
import { describe, it } from 'mocha'
33

4-
import Backendless, { forSuite, prepareMockRequest, APP_PATH, Utils } from '../helpers/sandbox'
4+
import Backendless, { API_KEY, APP_ID, forSuite, prepareMockRequest, APP_PATH, Utils } from '../helpers/sandbox'
55

66
describe('<Logging>', function() {
77

@@ -430,4 +430,85 @@ describe('<Logging>', function() {
430430
'message' : 'debug message - 2',
431431
})
432432
})
433+
434+
it('should apply default logging config', async () => {
435+
logger.fatal('fatal message')
436+
logger.error('error message')
437+
logger.warn('warn message')
438+
logger.info('info message')
439+
logger.debug('debug message')
440+
logger.trace('trace message')
441+
442+
const req = prepareMockRequest()
443+
444+
await Backendless.Logging.flush()
445+
446+
expect(req.body).to.deep.equal([
447+
{ 'log-level': 'FATAL', 'logger': loggerName, 'message': 'fatal message', timestamp: req.body[0].timestamp },
448+
{ 'log-level': 'ERROR', 'logger': loggerName, 'message': 'error message', timestamp: req.body[1].timestamp },
449+
{ 'log-level': 'WARN', 'logger': loggerName, 'message': 'warn message', timestamp: req.body[2].timestamp },
450+
{ 'log-level': 'INFO', 'logger': loggerName, 'message': 'info message', timestamp: req.body[3].timestamp },
451+
{ 'log-level': 'DEBUG', 'logger': loggerName, 'message': 'debug message', timestamp: req.body[4].timestamp },
452+
{ 'log-level': 'TRACE', 'logger': loggerName, 'message': 'trace message', timestamp: req.body[5].timestamp },
453+
])
454+
})
455+
456+
it('should apply log levels to logging config', async () => {
457+
prepareMockRequest([
458+
{
459+
name : loggerName,
460+
level: 'FATAL'
461+
}
462+
])
463+
464+
Backendless.initApp({
465+
appId : APP_ID,
466+
apiKey : API_KEY,
467+
logging: {
468+
defaultLevel: 'info',
469+
levels : {
470+
[loggerName]: 'warn'
471+
}
472+
}
473+
})
474+
475+
const req = prepareMockRequest()
476+
477+
logger.debug('debug message')
478+
logger.info('info message')
479+
logger.fatal('fatal message')
480+
logger.trace('trace message')
481+
482+
await Backendless.Logging.flush()
483+
484+
expect(req.body).to.deep.equal([
485+
{ 'log-level': 'FATAL', 'logger': loggerName, 'message': 'fatal message', timestamp: req.body[0].timestamp },
486+
])
487+
})
488+
489+
it('should not load log levels', async () => {
490+
Backendless.initApp({
491+
appId : APP_ID,
492+
apiKey : API_KEY,
493+
logging: {
494+
loadLevels: false,
495+
}
496+
})
497+
498+
const req = prepareMockRequest()
499+
500+
logger.debug('debug message')
501+
logger.info('info message')
502+
logger.fatal('fatal message')
503+
logger.trace('trace message')
504+
505+
await Backendless.Logging.flush()
506+
507+
expect(req.body).to.deep.equal([
508+
{ 'log-level': 'DEBUG', 'logger': loggerName, 'message': 'debug message', timestamp: req.body[0].timestamp },
509+
{ 'log-level': 'INFO', 'logger': loggerName, 'message': 'info message', timestamp: req.body[1].timestamp },
510+
{ 'log-level': 'FATAL', 'logger': loggerName, 'message': 'fatal message', timestamp: req.body[2].timestamp },
511+
{ 'log-level': 'TRACE', 'logger': loggerName, 'message': 'trace message', timestamp: req.body[3].timestamp },
512+
])
513+
})
433514
})

0 commit comments

Comments
 (0)