Skip to content

Commit 5919d14

Browse files
committed
feat: loggers + search engines models
1 parent 9c6a4f6 commit 5919d14

31 files changed

+433
-40
lines changed

server/core/kernel.js

+2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ module.exports = {
5151
async postBootMaster() {
5252
await WIKI.models.authentication.refreshStrategiesFromDisk()
5353
await WIKI.models.editors.refreshEditorsFromDisk()
54+
await WIKI.models.loggers.refreshLoggersFromDisk()
5455
await WIKI.models.renderers.refreshRenderersFromDisk()
56+
await WIKI.models.searchEngines.refreshSearchEnginesFromDisk()
5557
await WIKI.models.storage.refreshTargetsFromDisk()
5658

5759
await WIKI.auth.activateStrategies()

server/core/logger.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@ module.exports = {
1818

1919
// Init Console (default)
2020

21-
let loggerConsoleModule = require(`../modules/logging/console`)
22-
loggerConsoleModule.init(logger)
23-
this.loggers['console'] = loggerConsoleModule
21+
logger.add(new winston.transports.Console({
22+
level: WIKI.config.logLevel,
23+
prettyPrint: true,
24+
colorize: true,
25+
silent: false,
26+
timestamp: true
27+
}))
2428

2529
// _.forOwn(_.omitBy(WIKI.config.logging.loggers, s => s.enabled === false), (loggerConfig, loggerKey) => {
2630
// let loggerModule = require(`../modules/logging/${loggerKey}`)

server/db/migrations/2.0.0.js

+15
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ exports.up = knex => {
6565
table.string('createdAt').notNullable()
6666
table.string('updatedAt').notNullable()
6767
})
68+
// LOGGING ----------------------------
69+
.createTable('loggers', table => {
70+
table.increments('id').primary()
71+
table.string('key').notNullable().unique()
72+
table.boolean('isEnabled').notNullable().defaultTo(false)
73+
table.string('level').notNullable().defaultTo('warn')
74+
table.json('config')
75+
})
6876
// PAGE HISTORY ------------------------
6977
.createTable('pageHistory', table => {
7078
table.increments('id').primary()
@@ -103,6 +111,13 @@ exports.up = knex => {
103111
table.boolean('isEnabled').notNullable().defaultTo(false)
104112
table.json('config')
105113
})
114+
// SEARCH ------------------------------
115+
.createTable('searchEngines', table => {
116+
table.increments('id').primary()
117+
table.string('key').notNullable().unique()
118+
table.boolean('isEnabled').notNullable().defaultTo(false)
119+
table.json('config')
120+
})
106121
// SETTINGS ----------------------------
107122
.createTable('settings', table => {
108123
table.increments('id').primary()

server/models/loggers.js

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
const Model = require('objection').Model
2+
const path = require('path')
3+
const fs = require('fs-extra')
4+
const _ = require('lodash')
5+
const yaml = require('js-yaml')
6+
const commonHelper = require('../helpers/common')
7+
8+
/* global WIKI */
9+
10+
/**
11+
* Logger model
12+
*/
13+
module.exports = class Logger extends Model {
14+
static get tableName() { return 'loggers' }
15+
16+
static get jsonSchema () {
17+
return {
18+
type: 'object',
19+
required: ['key', 'isEnabled'],
20+
21+
properties: {
22+
id: {type: 'integer'},
23+
key: {type: 'string'},
24+
isEnabled: {type: 'boolean'},
25+
level: {type: 'string'},
26+
config: {type: 'object'}
27+
}
28+
}
29+
}
30+
31+
static async getLoggers() {
32+
return WIKI.models.loggers.query()
33+
}
34+
35+
static async refreshLoggersFromDisk() {
36+
let trx
37+
try {
38+
const dbLoggers = await WIKI.models.loggers.query()
39+
40+
// -> Fetch definitions from disk
41+
const loggersDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/logging'))
42+
let diskLoggers = []
43+
for (let dir of loggersDirs) {
44+
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/logging', dir, 'definition.yml'), 'utf8')
45+
diskLoggers.push(yaml.safeLoad(def))
46+
}
47+
WIKI.data.loggers = diskLoggers.map(logger => ({
48+
...logger,
49+
props: commonHelper.parseModuleProps(logger.props)
50+
}))
51+
52+
// -> Insert new loggers
53+
let newLoggers = []
54+
for (let logger of WIKI.data.loggers) {
55+
if (!_.some(dbLoggers, ['key', logger.key])) {
56+
newLoggers.push({
57+
key: logger.key,
58+
isEnabled: (logger.key === 'console'),
59+
level: logger.defaultLevel,
60+
config: _.transform(logger.props, (result, value, key) => {
61+
_.set(result, key, value.default)
62+
return result
63+
}, {})
64+
})
65+
} else {
66+
const loggerConfig = _.get(_.find(dbLoggers, ['key', logger.key]), 'config', {})
67+
await WIKI.models.loggers.query().patch({
68+
config: _.transform(logger.props, (result, value, key) => {
69+
if (!_.has(result, key)) {
70+
_.set(result, key, value.default)
71+
}
72+
return result
73+
}, loggerConfig)
74+
}).where('key', logger.key)
75+
}
76+
}
77+
if (newLoggers.length > 0) {
78+
trx = await WIKI.models.Objection.transaction.start(WIKI.models.knex)
79+
for (let logger of newLoggers) {
80+
await WIKI.models.loggers.query(trx).insert(logger)
81+
}
82+
await trx.commit()
83+
WIKI.logger.info(`Loaded ${newLoggers.length} new loggers: [ OK ]`)
84+
} else {
85+
WIKI.logger.info(`No new loggers found: [ SKIPPED ]`)
86+
}
87+
} catch (err) {
88+
WIKI.logger.error(`Failed to scan or load new loggers: [ FAILED ]`)
89+
WIKI.logger.error(err)
90+
if (trx) {
91+
trx.rollback()
92+
}
93+
}
94+
}
95+
96+
static async pageEvent({ event, page }) {
97+
const loggers = await WIKI.models.storage.query().where('isEnabled', true)
98+
if (loggers && loggers.length > 0) {
99+
_.forEach(loggers, logger => {
100+
WIKI.queue.job.syncStorage.add({
101+
event,
102+
logger,
103+
page
104+
}, {
105+
removeOnComplete: true
106+
})
107+
})
108+
}
109+
}
110+
}

server/models/searchEngines.js

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
const Model = require('objection').Model
2+
const path = require('path')
3+
const fs = require('fs-extra')
4+
const _ = require('lodash')
5+
const yaml = require('js-yaml')
6+
const commonHelper = require('../helpers/common')
7+
8+
/* global WIKI */
9+
10+
/**
11+
* SearchEngine model
12+
*/
13+
module.exports = class SearchEngine extends Model {
14+
static get tableName() { return 'searchEngines' }
15+
16+
static get jsonSchema () {
17+
return {
18+
type: 'object',
19+
required: ['key', 'isEnabled'],
20+
21+
properties: {
22+
id: {type: 'integer'},
23+
key: {type: 'string'},
24+
isEnabled: {type: 'boolean'},
25+
level: {type: 'string'},
26+
config: {type: 'object'}
27+
}
28+
}
29+
}
30+
31+
static async getSearchEngines() {
32+
return WIKI.models.searchEngines.query()
33+
}
34+
35+
static async refreshSearchEnginesFromDisk() {
36+
let trx
37+
try {
38+
const dbSearchEngines = await WIKI.models.searchEngines.query()
39+
40+
// -> Fetch definitions from disk
41+
const searchEnginesDirs = await fs.readdir(path.join(WIKI.SERVERPATH, 'modules/search'))
42+
let diskSearchEngines = []
43+
for (let dir of searchEnginesDirs) {
44+
const def = await fs.readFile(path.join(WIKI.SERVERPATH, 'modules/search', dir, 'definition.yml'), 'utf8')
45+
diskSearchEngines.push(yaml.safeLoad(def))
46+
}
47+
WIKI.data.searchEngines = diskSearchEngines.map(searchEngine => ({
48+
...searchEngine,
49+
props: commonHelper.parseModuleProps(searchEngine.props)
50+
}))
51+
52+
// -> Insert new searchEngines
53+
let newSearchEngines = []
54+
for (let searchEngine of WIKI.data.searchEngines) {
55+
if (!_.some(dbSearchEngines, ['key', searchEngine.key])) {
56+
newSearchEngines.push({
57+
key: searchEngine.key,
58+
isEnabled: false,
59+
config: _.transform(searchEngine.props, (result, value, key) => {
60+
_.set(result, key, value.default)
61+
return result
62+
}, {})
63+
})
64+
} else {
65+
const searchEngineConfig = _.get(_.find(dbSearchEngines, ['key', searchEngine.key]), 'config', {})
66+
await WIKI.models.searchEngines.query().patch({
67+
config: _.transform(searchEngine.props, (result, value, key) => {
68+
if (!_.has(result, key)) {
69+
_.set(result, key, value.default)
70+
}
71+
return result
72+
}, searchEngineConfig)
73+
}).where('key', searchEngine.key)
74+
}
75+
}
76+
if (newSearchEngines.length > 0) {
77+
trx = await WIKI.models.Objection.transaction.start(WIKI.models.knex)
78+
for (let searchEngine of newSearchEngines) {
79+
await WIKI.models.searchEngines.query(trx).insert(searchEngine)
80+
}
81+
await trx.commit()
82+
WIKI.logger.info(`Loaded ${newSearchEngines.length} new search engines: [ OK ]`)
83+
} else {
84+
WIKI.logger.info(`No new search engines found: [ SKIPPED ]`)
85+
}
86+
} catch (err) {
87+
WIKI.logger.error(`Failed to scan or load new search engines: [ FAILED ]`)
88+
WIKI.logger.error(err)
89+
if (trx) {
90+
trx.rollback()
91+
}
92+
}
93+
}
94+
95+
static async pageEvent({ event, page }) {
96+
const searchEngines = await WIKI.models.storage.query().where('isEnabled', true)
97+
if (searchEngines && searchEngines.length > 0) {
98+
_.forEach(searchEngines, logger => {
99+
WIKI.queue.job.syncStorage.add({
100+
event,
101+
logger,
102+
page
103+
}, {
104+
removeOnComplete: true
105+
})
106+
})
107+
}
108+
}
109+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
key: airbrake
2+
title: Airbrake
3+
description: Airbrake is the leading exception reporting service, currently providing error monitoring for 50,000 applications with support for 18 programming languages.
4+
author: requarks.io
5+
logo: https://static.requarks.io/logo/airbrake.svg
6+
website: https://airbrake.io/
7+
defaultLevel: warn
8+
props: {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// ------------------------------------
2+
// Airbrake
3+
// ------------------------------------
4+
5+
module.exports = {
6+
init (logger, conf) {
7+
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
key: bugsnag
2+
title: Bugsnag
3+
description: Bugsnag monitors apps for errors that impact customers & reports all diagnostic data.
4+
author: requarks.io
5+
logo: https://static.requarks.io/logo/bugsnag.svg
6+
website: https://www.bugsnag.com/
7+
defaultLevel: warn
8+
props:
9+
key:
10+
type: String
11+
title: Key
12+
hint: Bugsnag Project Notifier key

server/modules/logging/bugsnag/logger.js

-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ const _ = require('lodash')
77
// ------------------------------------
88

99
module.exports = {
10-
key: 'bugsnag',
11-
title: 'Bugsnag',
12-
props: ['key'],
1310
init (logger, conf) {
1411
let BugsnagLogger = winston.transports.BugsnagLogger = function (options) {
1512
this.name = 'bugsnagLogger'

server/modules/logging/console/logger.js

-22
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
key: disk
2+
title: Log Files
3+
description: Outputs log files on local disk.
4+
author: requarks.io
5+
logo: https://static.requarks.io/logo/local-fs.svg
6+
website: https://wiki.js.org
7+
defaultLevel: info
8+
props: {}

server/modules/logging/disk/logger.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// ------------------------------------
2+
// Disk
3+
// ------------------------------------
4+
5+
module.exports = {
6+
init (logger, conf) {
7+
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
key: eventlog
2+
title: Windows Event Log
3+
description: Report logs to the Windows Event Log
4+
author: requarks.io
5+
logo: https://static.requarks.io/logo/windows.svg
6+
website: https://wiki.js.org
7+
defaultLevel: warn
8+
props: {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// ------------------------------------
2+
// Windows Event Log
3+
// ------------------------------------
4+
5+
module.exports = {
6+
init (logger, conf) {
7+
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
key: loggly
2+
title: Loggly
3+
description: Log Analysis / Log Management by Loggly, the world's most popular log analysis & monitoring in the cloud.
4+
author: requarks.io
5+
logo: https://static.requarks.io/logo/loggly.svg
6+
website: https://www.loggly.com/
7+
defaultLevel: warn
8+
props:
9+
token:
10+
type: String
11+
title: Token
12+
hint: Loggly Token
13+
subdomain:
14+
type: String
15+
title: Subdomain
16+
hint: Loggly Subdomain

0 commit comments

Comments
 (0)