add webhook support, better colour resolving
This commit is contained in:
parent
2016bcede0
commit
5d7c9bb198
@ -17,7 +17,6 @@
|
||||
"array-callback-return": "warn",
|
||||
"array-bracket-newline": ["warn", "consistent"],
|
||||
"array-bracket-spacing": ["warn", "always", { "objectsInArrays": false, "arraysInArrays": false }],
|
||||
// "arrow-parens": "warn",
|
||||
"arrow-spacing": "warn",
|
||||
"block-scoped-var": "warn",
|
||||
"block-spacing": ["warn", "always"],
|
||||
@ -76,10 +75,6 @@
|
||||
],
|
||||
"lines-around-comment": "warn",
|
||||
"lines-around-directive": "warn",
|
||||
// "lines-between-class-members": [
|
||||
// "warn",
|
||||
// "always"
|
||||
// ],
|
||||
"max-classes-per-file": "warn",
|
||||
"max-nested-callbacks": "warn",
|
||||
"new-parens": "warn",
|
||||
@ -108,7 +103,6 @@
|
||||
"no-invalid-this": "warn",
|
||||
"no-iterator": "warn",
|
||||
"no-label-var": "warn",
|
||||
// "no-labels": "warn",
|
||||
"no-lone-blocks": "warn",
|
||||
"no-lonely-if": "warn",
|
||||
"no-loop-func": "warn",
|
||||
|
16
README.md
16
README.md
@ -2,12 +2,9 @@
|
||||
|
||||
Simple logger I wrote to have a unified system for logging throughout my projects.
|
||||
|
||||
## TODO
|
||||
- Discord webhook, need to write a separate package for that, don't want to add the entirety of d.js as a dep just for a webhook
|
||||
|
||||
## Features
|
||||
Split into Master and Client for logging between processes, where master resides on the master process and the clients on the spawned processes.
|
||||
Should be fairly trivial to modify it to work across nodes with websockets.
|
||||
Should be fairly trivial to modify it to work across nodes with websockets or some other IPC protocol.
|
||||
|
||||
**Note**
|
||||
When logging from a child process, the master logger expects the child process to be be in a wrapper containing at the very least an ID property to work properly (used for identifying which child the message came from).
|
||||
@ -28,6 +25,17 @@ The child processes are expected to be attached with the attach() method found i
|
||||
customColors: {}, // Supports any colours chalk.js supports, e.g. "warn": "green" will turn warning outputs green
|
||||
fileRotationFreq: 1, // How frequently to roate files in days - will not work with anything less than 1 day currently
|
||||
directory: './logs', // Directory in which to write log files
|
||||
logLevelMapping: {
|
||||
debug: 0,
|
||||
info: 1,
|
||||
status: 2,
|
||||
warn: 3,
|
||||
error: 4
|
||||
}
|
||||
broadcastLevel: 4, // Level at which to broadcast to webhook if supplied
|
||||
webhook: {
|
||||
url: string
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
"eslint": "^8.26.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@navy.gif/discord-webhook": "^1.0.0",
|
||||
"chalk": "^4.1.2",
|
||||
"moment": "^2.29.4"
|
||||
},
|
||||
|
@ -1,3 +1,11 @@
|
||||
const ColourCodes = {
|
||||
error: 0xe88388,
|
||||
warn: 0xf9d472,
|
||||
info: 0x76a9d8,
|
||||
debug: 0xd8abd7,
|
||||
status: 0x72d4d7
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
Types: [
|
||||
'error',
|
||||
@ -16,13 +24,7 @@ module.exports = {
|
||||
debug: 'magenta',
|
||||
status: 'cyanBright'
|
||||
},
|
||||
ColourCodes: {
|
||||
error: 0xe88388,
|
||||
warn: 0xf9d472,
|
||||
info: 0x76a9d8,
|
||||
debug: 0xd8abd7,
|
||||
status: 0x72d4d7
|
||||
},
|
||||
ColourCodes,
|
||||
MasterOptions: {
|
||||
fileRotationFreq: 1,
|
||||
directory: './logs',
|
||||
@ -31,6 +33,7 @@ module.exports = {
|
||||
customTypeMapping: {},
|
||||
customColors: {},
|
||||
guard: '_logger',
|
||||
broadcastLevel: 4,
|
||||
logLevel: 1,
|
||||
logLevelMapping: {
|
||||
debug: 0,
|
||||
@ -38,7 +41,10 @@ module.exports = {
|
||||
status: 2,
|
||||
warn: 3,
|
||||
error: 4
|
||||
}
|
||||
},
|
||||
webhook: {
|
||||
url: null
|
||||
},
|
||||
},
|
||||
ClientOptions: {
|
||||
guard: '_logger',
|
||||
|
@ -6,28 +6,31 @@ const path = require('node:path');
|
||||
const fs = require('node:fs');
|
||||
const { inspect } = require('node:util');
|
||||
|
||||
// const DiscordWebhook = require('@navy.gif/discord-webhook');
|
||||
const Defaults = require('./Defaults');
|
||||
|
||||
const DAY = 1000 * 60 * 60 * 24;
|
||||
|
||||
// TODO:
|
||||
// - Discord webhook, need to write a separate package for that, don't want to add the entirety of d.js as a dep just for a webhook
|
||||
class MasterLogger {
|
||||
|
||||
#_guard = null;
|
||||
#_logLevel = null;
|
||||
#_logLevelMapping = null;
|
||||
#_broadcastLevel = null;
|
||||
#webhook = null;
|
||||
|
||||
constructor (config = Defaults.MasterOptions) {
|
||||
|
||||
const {
|
||||
directory, customTypes, customStreams, customTypeMapping,
|
||||
customColors, guard, fileRotationFreq, logLevel, logLevelMapping
|
||||
customColors, guard, fileRotationFreq, logLevel, logLevelMapping,
|
||||
webhook, broadcastLevel
|
||||
} = { ...Defaults.MasterOptions, ...config };
|
||||
|
||||
this.directory = path.resolve(directory);
|
||||
if (!fs.existsSync(this.directory))
|
||||
fs.mkdirSync(this.directory, { recursive: true });
|
||||
this.#_broadcastLevel = broadcastLevel;
|
||||
this.#_logLevel = logLevel;
|
||||
this.#_logLevelMapping = { ...Defaults.MasterOptions.logLevelMapping, ...logLevelMapping };
|
||||
this.#_guard = guard;
|
||||
@ -40,6 +43,20 @@ class MasterLogger {
|
||||
}
|
||||
this.colours = { ...Defaults.Colours, ...customColors };
|
||||
|
||||
this.colourFuncs = Object.entries(this.colours).reduce((prev, [ type, colour ]) => {
|
||||
if (typeof colour === 'number')
|
||||
colour = `#${colour.toString(16)}`;
|
||||
else if (typeof colour !== 'string')
|
||||
throw new Error('Expecting colours to be either an integer, a hex string or one of the chalk compatible colour names');
|
||||
|
||||
if ((/#[A-Fa-f0-9]+/u).test(colour))
|
||||
prev[type] = { func: chalk.hex(colour), int: parseInt(colour.replace('#', ''), 16) };
|
||||
else
|
||||
prev[type] = { func: chalk[colour], int: Defaults.ColourCodes[type] || Defaults.ColourCodes.info };
|
||||
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
this.streamTypes = [ ...customStreams, 'error', 'default' ];
|
||||
this.streamTypeMapping = { ...Defaults.TypeStream, ...customTypeMapping };
|
||||
this.writeStreams = this.streamTypes.reduce((acc, type) => {
|
||||
@ -52,6 +69,12 @@ class MasterLogger {
|
||||
this.startDay = Math.floor(Date.now() / this.rotationFreq) * this.rotationFreq;
|
||||
this.rotateTO = setTimeout(this.rotateLogFiles.bind(this), this.startDay + this.rotationFreq - Date.now());
|
||||
|
||||
if (webhook && webhook.url)
|
||||
import('@navy.gif/discord-webhook').then(({ default: DiscordWebhook }) => {
|
||||
this.#webhook = new DiscordWebhook({ url: webhook.url });
|
||||
this.#webhook.fetch();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
get logLevel () {
|
||||
@ -83,9 +106,9 @@ class MasterLogger {
|
||||
write (type = 'info', text, { subheader = '', shard = null, broadcast = false } = {}) {
|
||||
|
||||
type = type.toLowerCase();
|
||||
let colour = this.colours[type];
|
||||
let colour = this.colourFuncs[type];
|
||||
if (!colour)
|
||||
colour = this.colours.info;
|
||||
colour = this.colourCodes.info;
|
||||
|
||||
if (typeof text !== 'string')
|
||||
text = inspect(text);
|
||||
@ -94,13 +117,17 @@ class MasterLogger {
|
||||
const maxChars = Math.max(...this.types.map(t => t.length));
|
||||
const spacer = ' '.repeat(maxChars - type.length);
|
||||
|
||||
// if (type === 'debug' && this._debug || type !== 'debug')
|
||||
if (this.#_logLevelMapping[type] >= this.#_logLevel)
|
||||
console.log(`${chalk[colour](type)}${spacer} ${chalk[colour](header)}: ${chalk.bold(subheader)}${text}`); // eslint-disable-line no-console
|
||||
console.log(`${colour.func(type)}${spacer} ${colour.func(header)}: ${chalk.bold(subheader)}${text}`); // eslint-disable-line no-console
|
||||
|
||||
if (broadcast) {
|
||||
// Send to webhook - TODO
|
||||
}
|
||||
if (broadcast || this.#_broadcastLevel <= this.#_logLevelMapping[type] && this.#webhook)
|
||||
this.#webhook.send({
|
||||
embeds: [{
|
||||
title: `[__${type.toUpperCase()}__] ${this._shard(shard)}`,
|
||||
description: `**${subheader}**\n${text}`,
|
||||
color: colour.int
|
||||
}]
|
||||
});
|
||||
|
||||
const streamType = this.streamTypeMapping[type] || 'default';
|
||||
if (this.writeStreams[streamType])
|
||||
|
11
test/test.js
11
test/test.js
@ -15,9 +15,16 @@ const main = async () => {
|
||||
customTypes: [ 'access' ],
|
||||
customStreams: [ 'access' ],
|
||||
customTypeMapping: { access: 'access', warn: 'error' },
|
||||
customColors: { access: 'green' },
|
||||
customColors: {
|
||||
access: 'green',
|
||||
// error: '#FF0000'
|
||||
},
|
||||
fileRotationFreq: 0.0001,
|
||||
logLevelMapping: { access: 2 }
|
||||
logLevelMapping: { access: 2 },
|
||||
broadcastLevel: 3,
|
||||
webhook: {
|
||||
url: 'https://discord.com/api/webhooks/1093874668886294548/uDMRD6g1lmq_2EZynsbKytzWoMM-0N4te0m61r_cv1BsSnDKDxG3fvI6sxSoG5t5b_xn'
|
||||
}
|
||||
});
|
||||
const child = ChildProcess.fork('./test/otherProcess.js');
|
||||
logger.attach(child);
|
||||
|
46
yarn.lock
46
yarn.lock
@ -36,6 +36,13 @@
|
||||
resolved "https://registry.corgi.wtf/@humanwhocodes%2fobject-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
|
||||
"@navy.gif/discord-webhook@^1.0.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.corgi.wtf/@navy.gif/discord-webhook/-/discord-webhook-1.1.0.tgz#b3f980bc42663ff1617c3756ce6c9184bc2a48f3"
|
||||
integrity sha512-+aJOfZD5kRoxEWU+sDAjX4qSRZ7vTPDBuFd6MsoaWC7ZSjSFuDqryyumBCs+w0EKU94xdxoH2qQ8ebFZ//ZugQ==
|
||||
dependencies:
|
||||
node-fetch "^3.3.1"
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.corgi.wtf/@nodelib%2ffs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
@ -146,6 +153,11 @@ cross-spawn@^7.0.2:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
data-uri-to-buffer@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.corgi.wtf/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
|
||||
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
|
||||
|
||||
debug@^4.1.1, debug@^4.3.2:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.corgi.wtf/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
@ -295,6 +307,14 @@ fastq@^1.6.0:
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.corgi.wtf/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
|
||||
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
|
||||
dependencies:
|
||||
node-domexception "^1.0.0"
|
||||
web-streams-polyfill "^3.0.3"
|
||||
|
||||
file-entry-cache@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.corgi.wtf/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
||||
@ -323,6 +343,13 @@ flatted@^3.1.0:
|
||||
resolved "https://registry.corgi.wtf/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
||||
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
||||
|
||||
formdata-polyfill@^4.0.10:
|
||||
version "4.0.10"
|
||||
resolved "https://registry.corgi.wtf/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
|
||||
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
|
||||
dependencies:
|
||||
fetch-blob "^3.1.2"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.corgi.wtf/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@ -481,6 +508,20 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.corgi.wtf/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
node-domexception@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.corgi.wtf/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
|
||||
|
||||
node-fetch@^3.3.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.corgi.wtf/node-fetch/-/node-fetch-3.3.1.tgz#b3eea7b54b3a48020e46f4f88b9c5a7430d20b2e"
|
||||
integrity sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==
|
||||
dependencies:
|
||||
data-uri-to-buffer "^4.0.0"
|
||||
fetch-blob "^3.1.4"
|
||||
formdata-polyfill "^4.0.10"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.corgi.wtf/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@ -635,6 +676,11 @@ uri-js@^4.2.2:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
web-streams-polyfill@^3.0.3:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.corgi.wtf/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
|
||||
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
|
||||
|
||||
which@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.corgi.wtf/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
||||
|
Loading…
Reference in New Issue
Block a user