diff --git a/src/client/app/admin/views/index.vue b/src/client/app/admin/views/index.vue
index b37bb8f7f5..4bce197edb 100644
--- a/src/client/app/admin/views/index.vue
+++ b/src/client/app/admin/views/index.vue
@@ -21,6 +21,7 @@
{{ $t('dashboard') }}
{{ $t('instance') }}
{{ $t('queue') }}
+ {{ $t('logs') }}
{{ $t('moderators') }}
{{ $t('users') }}
{{ $t('@.drive') }}
@@ -42,6 +43,7 @@
+
@@ -62,6 +64,7 @@ import { version } from '../../config';
import XDashboard from "./dashboard.vue";
import XInstance from "./instance.vue";
import XQueue from "./queue.vue";
+import XLogs from "./logs.vue";
import XModerators from "./moderators.vue";
import XEmoji from "./emoji.vue";
import XAnnouncements from "./announcements.vue";
@@ -71,7 +74,7 @@ import XDrive from "./drive.vue";
import XAbuse from "./abuse.vue";
import XFederation from "./federation.vue";
-import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks } from '@fortawesome/free-solid-svg-icons';
+import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks, faStream } from '@fortawesome/free-solid-svg-icons';
import { faGrin } from '@fortawesome/free-regular-svg-icons';
// Detect the user agent
@@ -84,6 +87,7 @@ export default Vue.extend({
XDashboard,
XInstance,
XQueue,
+ XLogs,
XModerators,
XEmoji,
XAnnouncements,
@@ -107,7 +111,8 @@ export default Vue.extend({
faHeadset,
faGlobe,
faExclamationCircle,
- faTasks
+ faTasks,
+ faStream
};
},
methods: {
diff --git a/src/client/app/admin/views/logs.vue b/src/client/app/admin/views/logs.vue
new file mode 100644
index 0000000000..1e76d141b4
--- /dev/null
+++ b/src/client/app/admin/views/logs.vue
@@ -0,0 +1,101 @@
+
+
+
+ {{ $t('logs') }}
+
+
+
+ {{ $t('domain') }}
+
+
+ {{ $t('level') }}
+
+
+
+
+
+
+
+
+
+
+
+ [{{ log.domain.join(' ') }}] {{ log.message }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/db/elasticsearch.ts b/src/db/elasticsearch.ts
index cbe6afbbb9..d54b01763b 100644
--- a/src/db/elasticsearch.ts
+++ b/src/db/elasticsearch.ts
@@ -1,6 +1,6 @@
import * as elasticsearch from 'elasticsearch';
import config from '../config';
-import Logger from '../misc/logger';
+import Logger from '../services/logger';
const esLogger = new Logger('es');
diff --git a/src/db/logger.ts b/src/db/logger.ts
new file mode 100644
index 0000000000..1f702c18e2
--- /dev/null
+++ b/src/db/logger.ts
@@ -0,0 +1,3 @@
+import Logger from '../services/logger';
+
+export const dbLogger = new Logger('db');
diff --git a/src/db/mongodb.ts b/src/db/mongodb.ts
index dedb289ce9..f82ced1765 100644
--- a/src/db/mongodb.ts
+++ b/src/db/mongodb.ts
@@ -18,7 +18,6 @@ export default db;
* MongoDB native module (officialy)
*/
import * as mongodb from 'mongodb';
-import Logger from '../misc/logger';
let mdb: mongodb.Db;
@@ -38,5 +37,3 @@ const nativeDbConn = async (): Promise => {
};
export { nativeDbConn };
-
-export const dbLogger = new Logger('db');
diff --git a/src/index.ts b/src/index.ts
index 6983ec722e..3206ee3d28 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -13,7 +13,7 @@ import * as portscanner from 'portscanner';
import * as isRoot from 'is-root';
import Xev from 'xev';
-import Logger from './misc/logger';
+import Logger from './services/logger';
import serverStats from './daemons/server-stats';
import notesStats from './daemons/notes-stats';
import loadConfig from './config/load';
@@ -25,7 +25,7 @@ import { checkMongoDB } from './misc/check-mongodb';
import { showMachineInfo } from './misc/show-machine-info';
const logger = new Logger('core', 'cyan');
-const bootLogger = logger.createSubLogger('boot', 'magenta');
+const bootLogger = logger.createSubLogger('boot', 'magenta', false);
const clusterLogger = logger.createSubLogger('cluster', 'orange');
const ev = new Xev();
@@ -73,7 +73,7 @@ function greet() {
console.log(chalk`${os.hostname()} {gray (PID: ${process.pid.toString()})}`);
bootLogger.info('Welcome to Misskey!');
- bootLogger.info(`Misskey v${pkg.version}`, true);
+ bootLogger.info(`Misskey v${pkg.version}`, null, true);
bootLogger.info('Misskey is maintained by @syuilo, @AyaMorisawa, @mei23, and @acid-chicken.');
}
@@ -90,21 +90,21 @@ async function masterMain() {
config = await init();
if (config.port == null) {
- bootLogger.error('The port is not configured. Please configure port.', true);
+ bootLogger.error('The port is not configured. Please configure port.', null, true);
process.exit(1);
}
if (process.platform === 'linux' && isWellKnownPort(config.port) && !isRoot()) {
- bootLogger.error('You need root privileges to listen on well-known port on Linux', true);
+ bootLogger.error('You need root privileges to listen on well-known port on Linux', null, true);
process.exit(1);
}
if (!await isPortAvailable(config.port)) {
- bootLogger.error(`Port ${config.port} is already in use`, true);
+ bootLogger.error(`Port ${config.port} is already in use`, null, true);
process.exit(1);
}
} catch (e) {
- bootLogger.error('Fatal error occurred during initialization', true);
+ bootLogger.error('Fatal error occurred during initialization', null, true);
process.exit(1);
}
@@ -117,7 +117,7 @@ async function masterMain() {
// start queue
require('./queue').default();
- bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, true);
+ bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, null, true);
}
/**
@@ -140,7 +140,7 @@ async function queueMain() {
// initialize app
await init();
} catch (e) {
- bootLogger.error('Fatal error occurred during initialization', true);
+ bootLogger.error('Fatal error occurred during initialization', null, true);
process.exit(1);
}
@@ -150,7 +150,7 @@ async function queueMain() {
const queue = require('./queue').default();
if (queue) {
- bootLogger.succ('Queue started', true);
+ bootLogger.succ('Queue started', null, true);
} else {
bootLogger.error('Queue not available');
}
@@ -175,7 +175,7 @@ function showEnvironment(): void {
if (env !== 'production') {
logger.warn('The environment is not in production mode.');
- logger.warn('DO NOT USE FOR PRODUCTION PURPOSE!', true);
+ logger.warn('DO NOT USE FOR PRODUCTION PURPOSE!', null, true);
}
logger.info(`You ${isRoot() ? '' : 'do not '}have root privileges`);
@@ -192,7 +192,7 @@ async function init(): Promise {
nodejsLogger.info(`Version ${runningNodejsVersion.join('.')}`);
if (!satisfyNodejsVersion) {
- nodejsLogger.error(`Node.js version is less than ${requiredNodejsVersion.join('.')}. Please upgrade it.`, true);
+ nodejsLogger.error(`Node.js version is less than ${requiredNodejsVersion.join('.')}. Please upgrade it.`, null, true);
process.exit(1);
}
@@ -209,7 +209,7 @@ async function init(): Promise {
process.exit(1);
}
if (exception.code === 'ENOENT') {
- configLogger.error('Configuration file not found', true);
+ configLogger.error('Configuration file not found', null, true);
process.exit(1);
}
throw exception;
@@ -221,7 +221,7 @@ async function init(): Promise {
try {
await checkMongoDB(config, bootLogger);
} catch (e) {
- bootLogger.error('Cannot connect to database', true);
+ bootLogger.error('Cannot connect to database', null, true);
process.exit(1);
}
diff --git a/src/misc/check-mongodb.ts b/src/misc/check-mongodb.ts
index f3839da31f..8e03db5d42 100644
--- a/src/misc/check-mongodb.ts
+++ b/src/misc/check-mongodb.ts
@@ -1,6 +1,6 @@
import { nativeDbConn } from '../db/mongodb';
import { Config } from '../config/types';
-import Logger from './logger';
+import Logger from '../services/logger';
import { lessThan } from '../prelude/array';
const requiredMongoDBVersion = [3, 6];
diff --git a/src/misc/logger.ts b/src/misc/logger.ts
deleted file mode 100644
index 1d159fb6a5..0000000000
--- a/src/misc/logger.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import * as cluster from 'cluster';
-import chalk from 'chalk';
-import * as dateformat from 'dateformat';
-import { program } from '../argv';
-
-export default class Logger {
- private domain: string;
- private color?: string;
- private parentLogger: Logger;
-
- constructor(domain: string, color?: string) {
- this.domain = domain;
- this.color = color;
- }
-
- public createSubLogger(domain: string, color?: string): Logger {
- const logger = new Logger(domain, color);
- logger.parentLogger = this;
- return logger;
- }
-
- private log(level: string, message: string, important = false, subDomains: string[] = []): void {
- if (program.quiet) return;
- if (process.env.NODE_ENV === 'test') return;
- const domain = this.color ? chalk.keyword(this.color)(this.domain) : chalk.white(this.domain);
- const domains = [domain].concat(subDomains);
- if (this.parentLogger) {
- this.parentLogger.log(level, message, important, domains);
- } else {
- const time = dateformat(new Date(), 'HH:MM:ss');
- const process = cluster.isMaster ? '*' : cluster.worker.id;
- let log = `${level} ${process}\t[${domains.join(' ')}]\t${message}`;
- if (program.withLogTime) log = chalk.gray(time) + ' ' + log;
- console.log(important ? chalk.bold(log) : log);
- }
- }
-
- public error(message: string | Error, important = false): void { // 実行を継続できない状況で使う
- this.log(important ? chalk.bgRed.white('ERR ') : chalk.red('ERR '), chalk.red(message.toString()), important);
- }
-
- public warn(message: string, important = false): void { // 実行を継続できるが改善すべき状況で使う
- this.log(chalk.yellow('WARN'), chalk.yellow(message), important);
- }
-
- public succ(message: string, important = false): void { // 何かに成功した状況で使う
- this.log(important ? chalk.bgGreen.white('DONE') : chalk.green('DONE'), chalk.green(message), important);
- }
-
- public debug(message: string, important = false): void { // デバッグ用に使う(開発者に必要だが利用者に不要な情報)
- if (process.env.NODE_ENV != 'production' || program.verbose) {
- this.log(chalk.gray('VERB'), chalk.gray(message), important);
- }
- }
-
- public info(message: string, important = false): void { // それ以外
- this.log(chalk.blue('INFO'), message, important);
- }
-}
diff --git a/src/misc/show-machine-info.ts b/src/misc/show-machine-info.ts
index a4d85edfe0..2aae019be2 100644
--- a/src/misc/show-machine-info.ts
+++ b/src/misc/show-machine-info.ts
@@ -1,6 +1,6 @@
import * as os from 'os';
import * as sysUtils from 'systeminformation';
-import Logger from './logger';
+import Logger from '../services/logger';
export async function showMachineInfo(parentLogger: Logger) {
const logger = parentLogger.createSubLogger('machine');
diff --git a/src/models/drive-file.ts b/src/models/drive-file.ts
index f3e21f209b..c31e9a709f 100644
--- a/src/models/drive-file.ts
+++ b/src/models/drive-file.ts
@@ -2,9 +2,10 @@ import * as mongo from 'mongodb';
import * as deepcopy from 'deepcopy';
import { pack as packFolder } from './drive-folder';
import { pack as packUser } from './user';
-import monkDb, { nativeDbConn, dbLogger } from '../db/mongodb';
+import monkDb, { nativeDbConn } from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import getDriveFileUrl, { getOriginalUrl } from '../misc/get-drive-file-url';
+import { dbLogger } from '../db/logger';
const DriveFile = monkDb.get('driveFiles.files');
DriveFile.createIndex('md5');
diff --git a/src/models/favorite.ts b/src/models/favorite.ts
index e3aa92c887..2008edbfaf 100644
--- a/src/models/favorite.ts
+++ b/src/models/favorite.ts
@@ -1,8 +1,9 @@
import * as mongo from 'mongodb';
import * as deepcopy from 'deepcopy';
-import db, { dbLogger } from '../db/mongodb';
+import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import { pack as packNote } from './note';
+import { dbLogger } from '../db/logger';
const Favorite = db.get('favorites');
Favorite.createIndex('userId');
diff --git a/src/models/log.ts b/src/models/log.ts
new file mode 100644
index 0000000000..f74332e940
--- /dev/null
+++ b/src/models/log.ts
@@ -0,0 +1,17 @@
+import * as mongo from 'mongodb';
+import db from '../db/mongodb';
+
+const Log = db.get('logs');
+Log.createIndex('createdAt', { expireAfterSeconds: 3600 * 24 * 3 });
+export default Log;
+
+export interface ILog {
+ _id: mongo.ObjectID;
+ createdAt: Date;
+ machine: string;
+ worker: string;
+ domain: string[];
+ level: string;
+ message: string;
+ data: any;
+}
diff --git a/src/models/note.ts b/src/models/note.ts
index 9bdf22e977..c3413164be 100644
--- a/src/models/note.ts
+++ b/src/models/note.ts
@@ -1,7 +1,7 @@
import * as mongo from 'mongodb';
import * as deepcopy from 'deepcopy';
import rap from '@prezzemolo/rap';
-import db, { dbLogger } from '../db/mongodb';
+import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import { length } from 'stringz';
import { IUser, pack as packUser } from './user';
@@ -11,6 +11,7 @@ import Reaction from './note-reaction';
import { packMany as packFileMany, IDriveFile } from './drive-file';
import Following from './following';
import Emoji from './emoji';
+import { dbLogger } from '../db/logger';
const Note = db.get('notes');
Note.createIndex('uri', { sparse: true, unique: true });
diff --git a/src/models/notification.ts b/src/models/notification.ts
index aedeafb522..75456af57b 100644
--- a/src/models/notification.ts
+++ b/src/models/notification.ts
@@ -1,9 +1,10 @@
import * as mongo from 'mongodb';
import * as deepcopy from 'deepcopy';
-import db, { dbLogger } from '../db/mongodb';
+import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import { IUser, pack as packUser } from './user';
import { pack as packNote } from './note';
+import { dbLogger } from '../db/logger';
const Notification = db.get('notifications');
Notification.createIndex('notifieeId');
diff --git a/src/models/user.ts b/src/models/user.ts
index 97c7037938..56e052ed46 100644
--- a/src/models/user.ts
+++ b/src/models/user.ts
@@ -1,7 +1,7 @@
import * as mongo from 'mongodb';
import * as deepcopy from 'deepcopy';
import rap from '@prezzemolo/rap';
-import db, { dbLogger } from '../db/mongodb';
+import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import { packMany as packNoteMany } from './note';
import Following from './following';
@@ -12,6 +12,7 @@ import config from '../config';
import FollowRequest from './follow-request';
import fetchMeta from '../misc/fetch-meta';
import Emoji from './emoji';
+import { dbLogger } from '../db/logger';
const User = db.get('users');
diff --git a/src/queue/logger.ts b/src/queue/logger.ts
index 99d88bd63b..d6d0774680 100644
--- a/src/queue/logger.ts
+++ b/src/queue/logger.ts
@@ -1,3 +1,3 @@
-import Logger from '../misc/logger';
+import Logger from '../services/logger';
export const queueLogger = new Logger('queue', 'orange');
diff --git a/src/queue/processors/http/process-inbox.ts b/src/queue/processors/http/process-inbox.ts
index 43170848f9..ea737593dc 100644
--- a/src/queue/processors/http/process-inbox.ts
+++ b/src/queue/processors/http/process-inbox.ts
@@ -7,7 +7,7 @@ import { resolvePerson, updatePerson } from '../../../remote/activitypub/models/
import { toUnicode } from 'punycode';
import { URL } from 'url';
import { publishApLogStream } from '../../../services/stream';
-import Logger from '../../../misc/logger';
+import Logger from '../../../services/logger';
import { registerOrFetchInstanceDoc } from '../../../services/register-or-fetch-instance-doc';
import Instance from '../../../models/instance';
import instanceChart from '../../../services/chart/instance';
diff --git a/src/remote/logger.ts b/src/remote/logger.ts
index cf2fe1e909..43b4f105aa 100644
--- a/src/remote/logger.ts
+++ b/src/remote/logger.ts
@@ -1,3 +1,3 @@
-import Logger from "../misc/logger";
+import Logger from "../services/logger";
export const remoteLogger = new Logger('remote', 'cyan');
diff --git a/src/server/api/endpoints/admin/logs.ts b/src/server/api/endpoints/admin/logs.ts
new file mode 100644
index 0000000000..b5dc7d7283
--- /dev/null
+++ b/src/server/api/endpoints/admin/logs.ts
@@ -0,0 +1,51 @@
+import $ from 'cafy';
+import define from '../../define';
+import Log from '../../../../models/log';
+
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireModerator: true,
+
+ params: {
+ limit: {
+ validator: $.optional.num.range(1, 100),
+ default: 30
+ },
+
+ level: {
+ validator: $.optional.nullable.str,
+ default: null as any
+ },
+
+ domain: {
+ validator: $.optional.nullable.str,
+ default: null as any
+ }
+ }
+};
+
+export default define(meta, async (ps) => {
+ const sort = {
+ _id: -1
+ };
+ const query = {} as any;
+
+ if (ps.level) query.level = ps.level;
+ if (ps.domain) {
+ let i = 0;
+ for (const d of ps.domain.split(' ')) {
+ query[`domain.${i}`] = d;
+ i++;
+ }
+ }
+
+ const logs = await Log
+ .find(query, {
+ limit: ps.limit,
+ sort: sort
+ });
+
+ return logs;
+});
diff --git a/src/server/api/limiter.ts b/src/server/api/limiter.ts
index f5c326f7d1..3d66172fd8 100644
--- a/src/server/api/limiter.ts
+++ b/src/server/api/limiter.ts
@@ -3,7 +3,7 @@ import limiterDB from '../../db/redis';
import { IEndpoint } from './endpoints';
import getAcct from '../../misc/acct/render';
import { IUser } from '../../models/user';
-import Logger from '../../misc/logger';
+import Logger from '../../services/logger';
const logger = new Logger('limiter');
diff --git a/src/server/api/logger.ts b/src/server/api/logger.ts
index 334a696331..0ea67a90eb 100644
--- a/src/server/api/logger.ts
+++ b/src/server/api/logger.ts
@@ -1,3 +1,3 @@
-import Logger from "../../misc/logger";
+import Logger from "../../services/logger";
export const apiLogger = new Logger('api');
diff --git a/src/server/index.ts b/src/server/index.ts
index 470562d802..7c51923f9e 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -23,10 +23,10 @@ import networkChart from '../services/chart/network';
import apiServer from './api';
import { sum } from '../prelude/array';
import User from '../models/user';
-import Logger from '../misc/logger';
+import Logger from '../services/logger';
import { program } from '../argv';
-export const serverLogger = new Logger('server', 'gray');
+export const serverLogger = new Logger('server', 'gray', false);
// Init app
const app = new Koa();
diff --git a/src/server/web/url-preview.ts b/src/server/web/url-preview.ts
index 9fda5f16f8..90c1a4930a 100644
--- a/src/server/web/url-preview.ts
+++ b/src/server/web/url-preview.ts
@@ -2,7 +2,7 @@ import * as Koa from 'koa';
import * as request from 'request-promise-native';
import summaly from 'summaly';
import fetchMeta from '../../misc/fetch-meta';
-import Logger from '../../misc/logger';
+import Logger from '../../services/logger';
const logger = new Logger('url-preview');
diff --git a/src/services/blocking/delete.ts b/src/services/blocking/delete.ts
index 425648f4cc..099fa14b37 100644
--- a/src/services/blocking/delete.ts
+++ b/src/services/blocking/delete.ts
@@ -4,7 +4,7 @@ import { renderActivity } from '../../remote/activitypub/renderer';
import renderBlock from '../../remote/activitypub/renderer/block';
import renderUndo from '../../remote/activitypub/renderer/undo';
import { deliver } from '../../queue';
-import Logger from '../../misc/logger';
+import Logger from '../logger';
const logger = new Logger('blocking/delete');
diff --git a/src/services/chart/index.ts b/src/services/chart/index.ts
index 2fabb55721..7a6470f4d8 100644
--- a/src/services/chart/index.ts
+++ b/src/services/chart/index.ts
@@ -8,7 +8,7 @@ import autobind from 'autobind-decorator';
import * as mongo from 'mongodb';
import db from '../../db/mongodb';
import { ICollection } from 'monk';
-import Logger from '../../misc/logger';
+import Logger from '../logger';
import { Schema } from '../../misc/schema';
const logger = new Logger('chart');
diff --git a/src/services/drive/logger.ts b/src/services/drive/logger.ts
index 979d282cc1..b66db9ed8f 100644
--- a/src/services/drive/logger.ts
+++ b/src/services/drive/logger.ts
@@ -1,3 +1,3 @@
-import Logger from "../../misc/logger";
+import Logger from "../logger";
export const driveLogger = new Logger('drive', 'blue');
diff --git a/src/services/following/create.ts b/src/services/following/create.ts
index 38f86fbf7d..1eaad750f7 100644
--- a/src/services/following/create.ts
+++ b/src/services/following/create.ts
@@ -13,7 +13,7 @@ import perUserFollowingChart from '../../services/chart/per-user-following';
import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc';
import Instance from '../../models/instance';
import instanceChart from '../../services/chart/instance';
-import Logger from '../../misc/logger';
+import Logger from '../logger';
import FollowRequest from '../../models/follow-request';
import { IdentifiableError } from '../../misc/identifiable-error';
diff --git a/src/services/following/delete.ts b/src/services/following/delete.ts
index 93f72b51d8..28268f1fd8 100644
--- a/src/services/following/delete.ts
+++ b/src/services/following/delete.ts
@@ -6,7 +6,7 @@ import renderFollow from '../../remote/activitypub/renderer/follow';
import renderUndo from '../../remote/activitypub/renderer/undo';
import { deliver } from '../../queue';
import perUserFollowingChart from '../../services/chart/per-user-following';
-import Logger from '../../misc/logger';
+import Logger from '../logger';
import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc';
import Instance from '../../models/instance';
import instanceChart from '../../services/chart/instance';
diff --git a/src/services/logger.ts b/src/services/logger.ts
new file mode 100644
index 0000000000..aa93954bc1
--- /dev/null
+++ b/src/services/logger.ts
@@ -0,0 +1,107 @@
+import * as cluster from 'cluster';
+import * as os from 'os';
+import chalk from 'chalk';
+import * as dateformat from 'dateformat';
+import { program } from '../argv';
+import Log from '../models/log';
+
+type Domain = {
+ name: string;
+ color: string;
+};
+
+type Level = 'error' | 'success' | 'warning' | 'debug' | 'info';
+
+export default class Logger {
+ private domain: Domain;
+ private parentLogger: Logger;
+ private store: boolean;
+
+ constructor(domain: string, color?: string, store = true) {
+ this.domain = {
+ name: domain,
+ color: color,
+ };
+ this.store = store;
+ }
+
+ public createSubLogger(domain: string, color?: string, store = true): Logger {
+ const logger = new Logger(domain, color, store);
+ logger.parentLogger = this;
+ return logger;
+ }
+
+ private log(level: Level, message: string, data: Record, important = false, subDomains: Domain[] = [], store = true): void {
+ if (program.quiet) return;
+ if (process.env.NODE_ENV === 'test') return;
+ if (!this.store) store = false;
+
+ if (this.parentLogger) {
+ this.parentLogger.log(level, message, data, important, [this.domain].concat(subDomains), store);
+ return;
+ }
+
+ const time = dateformat(new Date(), 'HH:MM:ss');
+ const worker = cluster.isMaster ? '*' : cluster.worker.id;
+ const l =
+ level === 'error' ? important ? chalk.bgRed.white('ERR ') : chalk.red('ERR ') :
+ level === 'warning' ? chalk.yellow('WARN') :
+ level === 'success' ? important ? chalk.bgGreen.white('DONE') : chalk.green('DONE') :
+ level === 'debug' ? chalk.gray('VERB') :
+ level === 'info' ? chalk.blue('INFO') :
+ null;
+ const domains = [this.domain].concat(subDomains).map(d => d.color ? chalk.keyword(d.color)(d.name) : chalk.white(d.name));
+ const m =
+ level === 'error' ? chalk.red(message) :
+ level === 'warning' ? chalk.yellow(message) :
+ level === 'success' ? chalk.green(message) :
+ level === 'debug' ? chalk.gray(message) :
+ level === 'info' ? message :
+ null;
+
+ let log = `${l} ${worker}\t[${domains.join(' ')}]\t${m}`;
+ if (program.withLogTime) log = chalk.gray(time) + ' ' + log;
+
+ console.log(important ? chalk.bold(log) : log);
+
+ if (store) {
+ Log.insert({
+ createdAt: new Date(),
+ machine: os.hostname(),
+ worker: worker,
+ domain: [this.domain].concat(subDomains).map(d => d.name),
+ level: level,
+ message: message,
+ data: data,
+ });
+ }
+ }
+
+ public error(x: string | Error, data?: Record, important = false): void { // 実行を継続できない状況で使う
+ if (x instanceof Error) {
+ data = data || {};
+ data.e = x;
+ this.log('error', x.toString(), data, important);
+ } else {
+ this.log('error', x, data, important);
+ }
+ }
+
+ public warn(message: string, data?: Record, important = false): void { // 実行を継続できるが改善すべき状況で使う
+ this.log('warning', message, data, important);
+ }
+
+ public succ(message: string, data?: Record, important = false): void { // 何かに成功した状況で使う
+ this.log('success', message, data, important);
+ }
+
+ public debug(message: string, data?: Record, important = false): void { // デバッグ用に使う(開発者に必要だが利用者に不要な情報)
+ if (process.env.NODE_ENV != 'production' || program.verbose) {
+ this.log('debug', message, data, important);
+ }
+ }
+
+ public info(message: string, data?: Record, important = false): void { // それ以外
+ this.log('info', message, data, important);
+ }
+}