w-syslog 1.0.0
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.
- package/.editorconfig +9 -0
- package/.eslintignore +3 -0
- package/.eslintrc.js +55 -0
- package/.github/workflows/ci-test.yml +24 -0
- package/.jsdoc +25 -0
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/SECURITY.md +5 -0
- package/babel.config.js +16 -0
- package/dist/formatter.umd.js +7 -0
- package/dist/formatter.umd.js.map +1 -0
- package/dist/w-syslog.umd.js +7 -0
- package/dist/w-syslog.umd.js.map +1 -0
- package/docs/WSyslog.html +362 -0
- package/docs/WSyslog.mjs.html +165 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/index.html +84 -0
- package/docs/scripts/collapse.js +39 -0
- package/docs/scripts/commonNav.js +28 -0
- package/docs/scripts/linenumber.js +25 -0
- package/docs/scripts/nav.js +12 -0
- package/docs/scripts/polyfill.js +4 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/scripts/prettify/lang-css.js +2 -0
- package/docs/scripts/prettify/prettify.js +28 -0
- package/docs/scripts/search.js +99 -0
- package/docs/styles/jsdoc.css +776 -0
- package/docs/styles/prettify.css +80 -0
- package/g.mjs +27 -0
- package/logs/2025-07-06.log +4 -0
- package/package.json +32 -0
- package/script.txt +18 -0
- package/src/WSyslog.mjs +93 -0
- package/src/formatter.mjs +77 -0
- package/test/WSyslog.test.mjs +50 -0
- package/toolg/addVersion.mjs +4 -0
- package/toolg/cleanFolder.mjs +4 -0
- package/toolg/gDistRollup.mjs +23 -0
- package/toolg/modifyReadme.mjs +4 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
.pln {
|
|
2
|
+
color: #ddd;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* string content */
|
|
6
|
+
.str {
|
|
7
|
+
color: #61ce3c;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* a keyword */
|
|
11
|
+
.kwd {
|
|
12
|
+
color: #fbde2d;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* a comment */
|
|
16
|
+
.com {
|
|
17
|
+
color: #aeaeae;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* a type name */
|
|
21
|
+
.typ {
|
|
22
|
+
color: #8da6ce;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* a literal value */
|
|
26
|
+
.lit {
|
|
27
|
+
color: #fbde2d;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* punctuation */
|
|
31
|
+
.pun {
|
|
32
|
+
color: #ddd;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* lisp open bracket */
|
|
36
|
+
.opn {
|
|
37
|
+
color: #000000;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* lisp close bracket */
|
|
41
|
+
.clo {
|
|
42
|
+
color: #000000;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* a markup tag name */
|
|
46
|
+
.tag {
|
|
47
|
+
color: #8da6ce;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* a markup attribute name */
|
|
51
|
+
.atn {
|
|
52
|
+
color: #fbde2d;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* a markup attribute value */
|
|
56
|
+
.atv {
|
|
57
|
+
color: #ddd;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* a declaration */
|
|
61
|
+
.dec {
|
|
62
|
+
color: #EF5050;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* a variable name */
|
|
66
|
+
.var {
|
|
67
|
+
color: #c82829;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* a function name */
|
|
71
|
+
.fun {
|
|
72
|
+
color: #4271ae;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* Specify class=linenums on a pre to get line numbering */
|
|
76
|
+
ol.linenums {
|
|
77
|
+
margin-top: 0;
|
|
78
|
+
margin-bottom: 0;
|
|
79
|
+
padding-bottom: 2px;
|
|
80
|
+
}
|
package/g.mjs
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import _ from 'lodash-es'
|
|
3
|
+
import w from 'wsemi'
|
|
4
|
+
import WSyslog from './src/WSyslog.mjs'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
w.fsCleanFolder('./logs')
|
|
8
|
+
|
|
9
|
+
let log = await WSyslog()
|
|
10
|
+
log.info({ event: 'runner', msg: 'start' })
|
|
11
|
+
log.warn({ event: 'monitor-memory', msg: 'usage-high' })
|
|
12
|
+
log.error({ event: 'crash', msg: 'db connection', code: 500 })
|
|
13
|
+
|
|
14
|
+
await w.delay(2000) //等待2秒讓pino能flush數據
|
|
15
|
+
|
|
16
|
+
let vpfs = w.fsTreeFolder('./logs')
|
|
17
|
+
// console.log('vpfs', vpfs)
|
|
18
|
+
|
|
19
|
+
let fp = _.get(vpfs, `0.path`, '')
|
|
20
|
+
|
|
21
|
+
let jj = fs.readFileSync(fp, 'utf8')
|
|
22
|
+
console.log(jj)
|
|
23
|
+
// {"level":30,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"runner","msg":"start"}
|
|
24
|
+
// {"level":40,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"monitor-memory","msg":"usage-high"}
|
|
25
|
+
// {"level":50,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"crash","msg":"db connection","code":500}
|
|
26
|
+
|
|
27
|
+
//node g.mjs
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{"level":30,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"runner","msg":"start"}
|
|
2
|
+
{"level":40,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"monitor-memory","msg":"usage-high"}
|
|
3
|
+
{"level":50,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"crash","msg":"db connection","code":500}
|
|
4
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "w-syslog",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/w-syslog.umd.js",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"lodash-es": "^4.17.21",
|
|
7
|
+
"node-disk-info": "^1.3.0",
|
|
8
|
+
"node-os-utils": "^1.3.7",
|
|
9
|
+
"pino": "^9.7.0",
|
|
10
|
+
"wsemi": "^1.8.11"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"w-package-tools": "^1.1.2"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "mocha --parallel --timeout 60000",
|
|
17
|
+
"deploy": "gh-pages -d docs"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/yuda-lyu/w-syslog.git"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"package",
|
|
25
|
+
"tool",
|
|
26
|
+
"log",
|
|
27
|
+
"pino",
|
|
28
|
+
"node"
|
|
29
|
+
],
|
|
30
|
+
"author": "yuda-lyu(semisphere)",
|
|
31
|
+
"license": "MIT"
|
|
32
|
+
}
|
package/script.txt
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#node toolg/addVersion.mjs
|
|
2
|
+
node toolg/modifyReadme.mjs
|
|
3
|
+
|
|
4
|
+
node toolg/cleanFolder.mjs
|
|
5
|
+
./node_modules/.bin/jsdoc -c .jsdoc
|
|
6
|
+
|
|
7
|
+
node toolg/gDistRollup.mjs
|
|
8
|
+
|
|
9
|
+
git add . -A
|
|
10
|
+
git commit -m 'modify: '
|
|
11
|
+
git push origin master:master
|
|
12
|
+
|
|
13
|
+
npm run deploy
|
|
14
|
+
|
|
15
|
+
#npm test
|
|
16
|
+
|
|
17
|
+
#npm publish
|
|
18
|
+
|
package/src/WSyslog.mjs
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import { fileURLToPath } from 'url'
|
|
3
|
+
import get from 'lodash-es/get.js'
|
|
4
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
5
|
+
import pino from 'pino'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// __dirname
|
|
9
|
+
let __filename = fileURLToPath(import.meta.url)
|
|
10
|
+
let __dirname = path.dirname(__filename)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 輸出log
|
|
15
|
+
*
|
|
16
|
+
* @class
|
|
17
|
+
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
18
|
+
* @param {String} [opt.timeCpuUsage=200] 輸入偵測CPU使用率時取樣時間數字,單位ms,預設200
|
|
19
|
+
* @returns {Object} 回傳事件物件
|
|
20
|
+
* @example
|
|
21
|
+
* import fs from 'fs'
|
|
22
|
+
* import _ from 'lodash-es'
|
|
23
|
+
* import w from 'wsemi'
|
|
24
|
+
* import WSyslog from './src/WSyslog.mjs'
|
|
25
|
+
*
|
|
26
|
+
* w.fsCleanFolder('./logs')
|
|
27
|
+
*
|
|
28
|
+
* let log = await WSyslog()
|
|
29
|
+
* log.info({ event: 'runner', msg: 'start' })
|
|
30
|
+
* log.warn({ event: 'monitor-memory', msg: 'usage-high' })
|
|
31
|
+
* log.error({ event: 'crash', msg: 'db connection', code: 500 })
|
|
32
|
+
*
|
|
33
|
+
* await w.delay(2000) //等待2秒讓pino能flush數據
|
|
34
|
+
*
|
|
35
|
+
* let vpfs = w.fsTreeFolder('./logs')
|
|
36
|
+
* // console.log('vpfs', vpfs)
|
|
37
|
+
*
|
|
38
|
+
* let fp = _.get(vpfs, `0.path`, '')
|
|
39
|
+
*
|
|
40
|
+
* let jj = fs.readFileSync(fp, 'utf8')
|
|
41
|
+
* console.log(jj)
|
|
42
|
+
* // {"level":30,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"runner","msg":"start"}
|
|
43
|
+
* // {"level":40,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"monitor-memory","msg":"usage-high"}
|
|
44
|
+
* // {"level":50,"time":1751780174415,"pid":24144,"hostname":"DESKTOP-6R7USAO","event":"crash","msg":"db connection","code":500}
|
|
45
|
+
*
|
|
46
|
+
*/
|
|
47
|
+
async function WSyslog(opt = {}) {
|
|
48
|
+
|
|
49
|
+
//fdLog
|
|
50
|
+
let fdLog = get(opt, 'fdLog')
|
|
51
|
+
if (!isestr(fdLog)) {
|
|
52
|
+
fdLog = './logs'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//interval
|
|
56
|
+
let interval = get(opt, 'interval')
|
|
57
|
+
if (interval !== 'day' && interval !== 'hr') {
|
|
58
|
+
interval = 'day'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 建立 logger,使用自訂 transport
|
|
62
|
+
let transport = pino.transport({
|
|
63
|
+
targets: [
|
|
64
|
+
{
|
|
65
|
+
|
|
66
|
+
// fatal: 60
|
|
67
|
+
// error: 50
|
|
68
|
+
// warn: 40
|
|
69
|
+
// info: 30
|
|
70
|
+
// debug: 20
|
|
71
|
+
// trace: 10
|
|
72
|
+
level: 'info', //僅紀錄info(30)以上
|
|
73
|
+
|
|
74
|
+
target: path.resolve(__dirname, './formatter.mjs'),
|
|
75
|
+
|
|
76
|
+
options: {
|
|
77
|
+
interval,
|
|
78
|
+
logDir: fdLog,
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
},
|
|
82
|
+
]
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
//log
|
|
86
|
+
let log = pino(transport)
|
|
87
|
+
// console.log('log', log)
|
|
88
|
+
|
|
89
|
+
return log
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
export default WSyslog
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { Writable } from 'stream'
|
|
4
|
+
import get from 'lodash-es/get.js'
|
|
5
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async function formatter(opt) {
|
|
9
|
+
//opt為各targets的options
|
|
10
|
+
|
|
11
|
+
//fdLog
|
|
12
|
+
let fdLog = get(opt, 'fdLog')
|
|
13
|
+
if (!isestr(fdLog)) {
|
|
14
|
+
fdLog = './logs'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//interval
|
|
18
|
+
let interval = get(opt, 'interval')
|
|
19
|
+
if (interval !== 'day' && interval !== 'hr') {
|
|
20
|
+
interval = 'day'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 建立 logs 資料夾
|
|
24
|
+
if (!fs.existsSync(fdLog)) {
|
|
25
|
+
fs.mkdirSync(fdLog, { recursive: true })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let currentFileStream = null
|
|
29
|
+
let currentTimeKey = ''
|
|
30
|
+
|
|
31
|
+
let getTimeKey = () => {
|
|
32
|
+
let d = new Date()
|
|
33
|
+
if (interval === 'hr') {
|
|
34
|
+
return d.toISOString().slice(0, 13).replace(/:/g, '-') // e.g., 2025-07-06T14
|
|
35
|
+
}
|
|
36
|
+
return d.toISOString().slice(0, 10) // e.g., 2025-07-06
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let getFilePath = (timeKey) => {
|
|
40
|
+
let fn = `${timeKey}.log`
|
|
41
|
+
return path.join(fdLog, fn)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let switchFileIfNeeded = () => {
|
|
45
|
+
let newKey = getTimeKey()
|
|
46
|
+
if (newKey !== currentTimeKey) {
|
|
47
|
+
currentTimeKey = newKey
|
|
48
|
+
let filePath = getFilePath(newKey)
|
|
49
|
+
if (currentFileStream) currentFileStream.end()
|
|
50
|
+
currentFileStream = fs.createWriteStream(filePath, { flags: 'a' })
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 初始建立檔案
|
|
55
|
+
switchFileIfNeeded()
|
|
56
|
+
|
|
57
|
+
let stream = new Writable({
|
|
58
|
+
write(chunk, encoding, callback) {
|
|
59
|
+
try {
|
|
60
|
+
switchFileIfNeeded()
|
|
61
|
+
|
|
62
|
+
// 將 Buffer 轉為字串,確保正確處理換行
|
|
63
|
+
const str = Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk)
|
|
64
|
+
|
|
65
|
+
currentFileStream.write(str + '\n', callback)
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
callback(err)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
return stream
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
export default formatter
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import assert from 'assert'
|
|
3
|
+
import _ from 'lodash-es'
|
|
4
|
+
import w from 'wsemi'
|
|
5
|
+
import WSyslog from '../src/WSyslog.mjs'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
describe('WSyslog', function() {
|
|
9
|
+
|
|
10
|
+
it('test', async function() {
|
|
11
|
+
|
|
12
|
+
w.fsCleanFolder('./logs')
|
|
13
|
+
|
|
14
|
+
let log = await WSyslog()
|
|
15
|
+
log.info({ event: 'runner', msg: 'start' })
|
|
16
|
+
log.warn({ event: 'monitor-memory', msg: 'usage-high' })
|
|
17
|
+
log.error({ event: 'crash', msg: 'db connection', code: 500 })
|
|
18
|
+
|
|
19
|
+
await w.delay(2000) //等待2秒讓pino能flush數據
|
|
20
|
+
|
|
21
|
+
let vpfs = w.fsTreeFolder('./logs')
|
|
22
|
+
// console.log('vpfs', vpfs)
|
|
23
|
+
|
|
24
|
+
let fp = _.get(vpfs, `0.path`, '')
|
|
25
|
+
|
|
26
|
+
let jj = fs.readFileSync(fp, 'utf8')
|
|
27
|
+
|
|
28
|
+
let ss = w.sep(jj, '\n')
|
|
29
|
+
|
|
30
|
+
let r = _.map(ss, (j) => {
|
|
31
|
+
let v = JSON.parse(j)
|
|
32
|
+
let event = _.get(v, 'event')
|
|
33
|
+
let msg = _.get(v, 'msg')
|
|
34
|
+
return {
|
|
35
|
+
event,
|
|
36
|
+
msg,
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
// console.log('r', r)
|
|
40
|
+
|
|
41
|
+
let rr = [
|
|
42
|
+
{ event: 'runner', msg: 'start' },
|
|
43
|
+
{ event: 'monitor-memory', msg: 'usage-high' },
|
|
44
|
+
{ event: 'crash', msg: 'db connection' },
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
assert.strict.deepEqual(r, rr)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import rollupFiles from 'w-package-tools/src/rollupFiles.mjs'
|
|
2
|
+
import getFiles from 'w-package-tools/src/getFiles.mjs'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
let fdSrc = './src'
|
|
6
|
+
let fdTar = './dist'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
rollupFiles({
|
|
10
|
+
fns: getFiles(fdSrc),
|
|
11
|
+
fdSrc,
|
|
12
|
+
fdTar,
|
|
13
|
+
nameDistType: 'kebabCase',
|
|
14
|
+
globals: {
|
|
15
|
+
'node-disk-info': 'node-disk-info',
|
|
16
|
+
'node-os-utils': 'node-os-utils',
|
|
17
|
+
},
|
|
18
|
+
external: [
|
|
19
|
+
'node-disk-info',
|
|
20
|
+
'node-os-utils',
|
|
21
|
+
],
|
|
22
|
+
})
|
|
23
|
+
|