完成日志模块
commit
ab39ac8cc7
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
._*
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
|
||||||
|
node_modules/
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,35 @@
|
||||||
|
![module info](https://nodei.co/npm/@gm5/logs.png?downloads=true&downloadRank=true&stars=true)
|
||||||
|
|
||||||
|
# @gm5/logs
|
||||||
|
|
||||||
|
> 日志存储拓展。
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @gm5/logs
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Logs from '@gm5/logs'
|
||||||
|
|
||||||
|
// 安装时传入日志目录
|
||||||
|
app.install(Logs, './data/logs')
|
||||||
|
|
||||||
|
|
||||||
|
app.$$logs.info('hello world')
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
安装之后, 有3个对外的方法, 对应3个等级的日志, 即
|
||||||
|
|
||||||
|
+ .info(msg`<String>`)
|
||||||
|
+ .warn(msg`<String>`)
|
||||||
|
+ .error(msg`<String>`)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* 日志记录
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2020/10/06 20:20:30
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { fork } from 'child_process'
|
||||||
|
import url from 'url'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
var __dirname = path.dirname(url.fileURLToPath(import.meta.url))
|
||||||
|
var child = fork(path.join(__dirname, 'logs.js'))
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'logs',
|
||||||
|
install(dir) {
|
||||||
|
// 在初始化之前写入的日志, 会失败, 所以要先扔进临时队列中
|
||||||
|
// 初始化之后再写入
|
||||||
|
var queue = []
|
||||||
|
var ready = false
|
||||||
|
|
||||||
|
child.on('message', _ => {
|
||||||
|
child.send({ type: 'init', dir })
|
||||||
|
ready = true
|
||||||
|
post()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 发送日志
|
||||||
|
function post(item) {
|
||||||
|
if (item) {
|
||||||
|
queue.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ready) {
|
||||||
|
while (queue.length) {
|
||||||
|
child.send(queue.shift())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
info(msg) {
|
||||||
|
post({ type: 'info', msg })
|
||||||
|
},
|
||||||
|
warn(msg) {
|
||||||
|
post({ type: 'warn', msg })
|
||||||
|
},
|
||||||
|
error(msg) {
|
||||||
|
post({ type: 'error', msg })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
import Queue from './queue.js'
|
||||||
|
|
||||||
|
var list = new Queue()
|
||||||
|
var file
|
||||||
|
var currSize = 0
|
||||||
|
var ws
|
||||||
|
var ready = false
|
||||||
|
|
||||||
|
list.on('data', _ => {
|
||||||
|
while (list.size) {
|
||||||
|
ws.write(list.shift())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
process.on('message', _ => {
|
||||||
|
//
|
||||||
|
switch (_.type) {
|
||||||
|
case 'init':
|
||||||
|
file = path.resolve(_.dir, 'app_debug.log')
|
||||||
|
ws = fs.createWriteStream(file, { flags: 'a' })
|
||||||
|
ws.once('ready', _ => {
|
||||||
|
ready = true
|
||||||
|
list.emit('data')
|
||||||
|
currSize = fs.statSync(file).size
|
||||||
|
})
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
var now = new Date().toISOString()
|
||||||
|
var data = `[${_.type}] ${now} ${_.msg}\n`
|
||||||
|
var len = Buffer.byteLength(data)
|
||||||
|
var id = 1
|
||||||
|
|
||||||
|
list.append(data)
|
||||||
|
|
||||||
|
if (ready) {
|
||||||
|
// 日志文件大于512MB, 自动分割文件
|
||||||
|
if (currSize + len > 1024 * 1024 * 512) {
|
||||||
|
ready = false
|
||||||
|
ws.close()
|
||||||
|
|
||||||
|
try {
|
||||||
|
// fs.constants.F_OK
|
||||||
|
while (fs.accessSync(`${file}.${id}`, 0) === undefined) {
|
||||||
|
id++
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
fs.renameSync(file, `${file}.${id}`)
|
||||||
|
ws = fs.createWriteStream(file, { flags: 'a' })
|
||||||
|
|
||||||
|
currSize = len
|
||||||
|
ws.once('ready', _ => {
|
||||||
|
ready = true
|
||||||
|
list.emit('data')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
currSize += len
|
||||||
|
list.emit('data')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 发送一个空消息, 通知主进程已经就绪
|
||||||
|
process.send(null)
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"name": "@gm5/logs",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"description": "日志存储拓展",
|
||||||
|
"main": "index.js",
|
||||||
|
"author": "yutent",
|
||||||
|
"keywords": [
|
||||||
|
"fivejs",
|
||||||
|
"logs"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/bytedo/gmf.logs.git",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* 简易版队列
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2020/10/07 00:22:26
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { EventEmitter } from 'events'
|
||||||
|
import { inherits } from 'util'
|
||||||
|
|
||||||
|
export default class Queue {
|
||||||
|
constructor() {
|
||||||
|
this.__store__ = []
|
||||||
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
return this.__store__.length
|
||||||
|
}
|
||||||
|
|
||||||
|
append(item) {
|
||||||
|
this.__store__.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
shift() {
|
||||||
|
return this.__store__.shift()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(Queue, EventEmitter)
|
Loading…
Reference in New Issue