initial commit 0.1.0
commit
5d3bf04dbb
|
@ -0,0 +1,15 @@
|
||||||
|
env:
|
||||||
|
node: true
|
||||||
|
es2021: true
|
||||||
|
mocha: true
|
||||||
|
extends:
|
||||||
|
- standard
|
||||||
|
parserOptions:
|
||||||
|
ecmaVersion: 12
|
||||||
|
sourceType: module
|
||||||
|
rules:
|
||||||
|
indent: ["error", 2]
|
||||||
|
no-console: 0
|
||||||
|
semi: ["error", "never"]
|
||||||
|
# linebreak-style: ["error", "unix"]
|
||||||
|
quotes: ["error", "single"]
|
|
@ -0,0 +1,3 @@
|
||||||
|
/node_modules/
|
||||||
|
/coverage/
|
||||||
|
*.yaml
|
|
@ -0,0 +1,3 @@
|
||||||
|
test/
|
||||||
|
*.test.js
|
||||||
|
example/
|
|
@ -0,0 +1,10 @@
|
||||||
|
import db from 'nedb-promises'
|
||||||
|
|
||||||
|
const dbfile = 'example/history.db'
|
||||||
|
|
||||||
|
const history = db.create(dbfile)
|
||||||
|
|
||||||
|
;
|
||||||
|
(async function () {
|
||||||
|
console.log(await history.find({ time: { $gt: 1 } }))
|
||||||
|
})()
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { write } from '../src/history.js'
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
path: 'example/history.db',
|
||||||
|
name: 'example',
|
||||||
|
clear: true,
|
||||||
|
keys: {
|
||||||
|
test: 'custom common key'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const event = write(opts)
|
||||||
|
|
||||||
|
event('something just happened')
|
||||||
|
event({ state: 'on', zone: 5, msg: 'another thing just happened' })
|
||||||
|
event('history writing again')
|
||||||
|
setTimeout(() => (event('interval')), 10000)
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"ignore": [
|
||||||
|
"example/*.json"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"name": "@uci-utils/history",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Maintain a history file of events in nljson",
|
||||||
|
"main": "./src/history.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"testd": "./node_modules/.bin/nodemon --exec './node_modules/.bin/mocha --timeout 30000' || exit 1",
|
||||||
|
"test": "./node_modules/.bin/mocha --timeout 30000 || exit 0",
|
||||||
|
"dev:write": "UCI_ENV=dev ./node_modules/.bin/nodemon example/write",
|
||||||
|
"dev:read": "UCI_ENV=dev ./node_modules/.bin/nodemon example/read",
|
||||||
|
"read": "node example/read",
|
||||||
|
"pro": "UCI_ENV='pro' node example/example",
|
||||||
|
"pro:path": "UCI_LOG_PATH=./example/example.log npm run pro"
|
||||||
|
},
|
||||||
|
"author": "David Kebler",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/uCOMmandIt/uci-changeme.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"nodejs",
|
||||||
|
"history",
|
||||||
|
"json",
|
||||||
|
"log"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/uCOMmandIt/uci-changeme/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/uCOMmandIt/uci-changeme#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"debounce-fn": "^5.0.0",
|
||||||
|
"env-paths": "^2.2.1",
|
||||||
|
"make-dir": "^3.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"eslint": "^7.28.0",
|
||||||
|
"eslint-config-standard": "^16.0.3",
|
||||||
|
"mocha": "^9.0.0",
|
||||||
|
"nedb-promises": "^4.1.5",
|
||||||
|
"nodemon": "^2.0.7"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
# UCommandIt JSONL History
|
||||||
|
#### maintain history file of events in newline json for a process
|
||||||
|
|
||||||
|
## How to by Example
|
|
@ -0,0 +1,52 @@
|
||||||
|
import envPaths from 'env-paths'
|
||||||
|
import { sync as mkdir } from 'make-dir'
|
||||||
|
import { dirname } from 'path'
|
||||||
|
import { createWriteStream, createReadStream } from 'fs'
|
||||||
|
import crypto from 'crypto'
|
||||||
|
import debounce from 'debounce-fn'
|
||||||
|
|
||||||
|
function write (opts = {}) {
|
||||||
|
const path = opts.path ? opts.path : `${envPaths(opts.name || 'history', { suffix: null }).log}/${opts.name || process.pid}.log`
|
||||||
|
mkdir(dirname(path)) // makes recursively for any missing parent directories
|
||||||
|
|
||||||
|
const create = (path, clear) => {
|
||||||
|
const stream = createWriteStream(path, { flags: `${clear ? 'w' : 'a'}` })
|
||||||
|
// todo make sure stream was made
|
||||||
|
stream.on('close', (data) => {
|
||||||
|
console.log('the stream to history file was closed')
|
||||||
|
})
|
||||||
|
return stream
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = create(path, opts.clear)
|
||||||
|
|
||||||
|
const _write = (obj) => {
|
||||||
|
if (output.writable) {
|
||||||
|
const tStamp = new Date()
|
||||||
|
const keys = {
|
||||||
|
_id: crypto.randomBytes(8).toString('hex'),
|
||||||
|
time: tStamp.getTime(),
|
||||||
|
datetime: tStamp.toString(),
|
||||||
|
utc: tStamp.toISOString()
|
||||||
|
}
|
||||||
|
if (typeof obj === 'string') obj = { msg: obj }
|
||||||
|
obj = Object.assign(keys, opts.keys, obj)
|
||||||
|
console.log('writing', obj)
|
||||||
|
output.write(JSON.stringify(obj) + '\n', function () {
|
||||||
|
debounce(output.destroy.bind(output), { wait: opts.close || 5000 })()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log('there is no stream, recreating')
|
||||||
|
output = create(path)
|
||||||
|
_write(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _write
|
||||||
|
}
|
||||||
|
|
||||||
|
function view (handler, opts) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default write
|
||||||
|
export { write, view }
|
|
@ -0,0 +1,92 @@
|
||||||
|
import logger from '../src/logger.js'
|
||||||
|
import { expect } from 'chai'
|
||||||
|
import { it } from 'mocha'
|
||||||
|
import { stdout } from 'test-console'
|
||||||
|
//https://github.com/jamesshore/test-console
|
||||||
|
|
||||||
|
describe('JSON Logging Utility Testing ',async ()=> {
|
||||||
|
|
||||||
|
let log
|
||||||
|
// let captured = stdout.inspect().output
|
||||||
|
// let capture = stdout.inspect
|
||||||
|
// let restore = stdout.inspect().restore
|
||||||
|
//
|
||||||
|
class LogTest {
|
||||||
|
constructor(opts) {
|
||||||
|
log = logger({
|
||||||
|
name: 'test',
|
||||||
|
id: opts.id,
|
||||||
|
file: 'example/example.js',
|
||||||
|
// class: 'LogTest',
|
||||||
|
// repo:'test repo'
|
||||||
|
package:'@uci-utils/test'
|
||||||
|
})
|
||||||
|
// console.log('env',process.env.UCI_ENV)
|
||||||
|
}
|
||||||
|
async logit(level,msg,props={}) {
|
||||||
|
Object.assign(props,{msg:msg})
|
||||||
|
log[level](props)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO this is available from the logger as .levels
|
||||||
|
let levelName = {
|
||||||
|
10:'trace',
|
||||||
|
20:'debug',
|
||||||
|
30:'info',
|
||||||
|
40:'warn',
|
||||||
|
50:'error',
|
||||||
|
60:'fatal'
|
||||||
|
}
|
||||||
|
|
||||||
|
let logtest = {}
|
||||||
|
let inspect = {}
|
||||||
|
|
||||||
|
beforeEach( () => {
|
||||||
|
// console.log('starting console capture')
|
||||||
|
inspect = stdout.inspect()
|
||||||
|
})
|
||||||
|
afterEach( () => {
|
||||||
|
inspect.restore()
|
||||||
|
// console.log('console.restored')
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
it('check dev output to console' , async function () {
|
||||||
|
// setup
|
||||||
|
let msg='test'
|
||||||
|
let level = 'info'
|
||||||
|
let moreprops = {}
|
||||||
|
process.env.UCI_ENV='dev'
|
||||||
|
logtest = new LogTest({id:'someid'})
|
||||||
|
|
||||||
|
// create log to stdout
|
||||||
|
logtest.logit(level,msg,moreprops)
|
||||||
|
|
||||||
|
// test stdout response
|
||||||
|
let response = inspect.output[0]
|
||||||
|
expect(response).to.have.string(level.toUpperCase()) &&
|
||||||
|
expect(response).to.have.string(msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('check json output' , async function () {
|
||||||
|
// setup
|
||||||
|
let msg='test'
|
||||||
|
let level = 'info'
|
||||||
|
let moreprops = {}
|
||||||
|
process.env.UCI_ENV='dev'
|
||||||
|
process.env.UCI_LOG_JSON=true
|
||||||
|
logtest = new LogTest({id:'someid'})
|
||||||
|
|
||||||
|
// create log to stdout
|
||||||
|
logtest.logit(level,msg,moreprops)
|
||||||
|
|
||||||
|
// test stdout response
|
||||||
|
let response = inspect.output[0]
|
||||||
|
response = JSON.parse(response)
|
||||||
|
expect(response.msg).to.equal(msg) &&
|
||||||
|
expect(levelName[response.level]).to.equal(level)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
})
|
Loading…
Reference in New Issue