timequerylog
v45.1.0
Published
Structured (JSON) logging separated into files per hour of day, with query.
Downloads
136
Maintainers
Readme
(See also tql-cli command line tool.)
JSONL (newline-separated JSON) logging separated into a files per hour of day with simple query between start and end time with match function.
The idea is to make it more efficient to query logs for a specific time period or type of data/event by breaking up the files in a consistent way.
You may want to use sub-types to break out data to improve efficiency when the
sub-type data doesn't always need to be queried immediately.
For example, instead of logging all details of an error type you may log
a main error type with the core details of errors and a separate error-details
type including info such as stack traces.
Usage
Log some data
import {log} from 'timequerylog';
log('request', {url:'http://www.reddit.com/'});Read last record for a type
import {latest} from 'timequerylog';
latest('request').then(row => console.log(row));Query data with a timestamp after 1/1/1995 GMT
import {query} from 'timequerylog';
query('request', new Date('01-01-1995'), new Date())
.then(rows => console.log(rows));Set directory for logging, don't repeat rows
import {config} from 'timequerylog';
config({path:process.cwd()+'/datalog', noRepeat: true});Log using a different time than the present
log('req',{cat:100}, new Date('2015-05-01T23:50:59.392Z'));Query logs from last 30 minutes matching function
query('req', null, null, d => d.amount > 1000).then(console.log);Return logs as an object mode stream
const matched = queryOpts({type:'request', start: new Date('2016-10-22 10:00 AM'),
end: new Date('2016-10-23')});
matched.on('data', console.log);Match, map results, convert time to MS since epoch, and return CSV text stream
let i = 0;
const csvStream = queryOpts({type:'event', csv: true, timeMS: true,
match: r => r.category == 'update',
start: new Date('1995-12-25'),
map: (r)=>{r.row = i++;return r}});
csvStream.pipe(process.stdout);Increment
let n = await incr('test'); // n = 1
n = await incr('test'); // n = 2
let m = await incr('test2',Date.now())
// if m was not previously incremented
// then m is Date.now()
// otherwise previous m + 1
const unixTime = Math.round(Date.now()/1000));
// actually saves unixTime - 1
await setIncr('test2', unixTime);
n = await incr('test2');
// n == unixTime
// need to load first with async call
let load = incr('test3',Date.now());
// loaded into memory, can now incr in memory
// and save after immediate return
let imm = incrNow('test3');
// if the process is killed suddenly
// without Node.js events completing, may not save
// updated value..
getTypes, queryMultiArray, high res time (hrms)
async function testMulti() {
console.log("Current high-res time:", hrms());
const types = await getTypes('*');
console.log(types);
const req = await getTypes('r*');
console.log(req);
log('testhr', {n:'tom',hrtime:hrms()});
log('testhr', {n:'bob',hrtime:hrms()});
await delay(10);
const args = { typeGlob: '*', start: new Date('1980-01-01'),
end: Date.now() };
const results = await queryMultiArray(args);
console.log(results);
}Functions/Options
log(type, object, time = current time)
Uses JSON stream to log some data to the file ./[type]_GMT/DATE/HOUR.
Returns a promise.
queryRecent(type)
Return a promise with data from the last 30 minutes for type. Searches JSON streamed files starting
from directory ./[type]_GMT.
query(type, startDate, endDate, matchFunction)
Returns a promise with data for type between startDate and endDate where matchFunction
returns true. Searches JSONL files starting from directory ./[type]_GMT.
config(opts)
Set configuration options. Defaults are: {path: process.cwd(), noRepeat: false},
noRepeat:{[type]:true} makes it ignore rows that are duplicates (besides time).
To delete files older than X days, specify
config({path:'datalog'}, deleteOldDays: {event: 100}}) --
deletes old 'event' type files 100 days or older.
queryOpts({type, start, end, match = (d=>true), csv=false,map, timeMS=false})
This query function takes an options object and returns either an objectMode stream or a CSV stream.
If end is not specified the current time is used. If start is not specified then end-30 minutes is
used. map is an optional function to modify rows. timeMS will return time as MS since epoch.
incr(key, init=0) or incrNow(key, init) (non-promise version)
Increment key and return new value. Stored in file key_INCR. Optionally init at some number.
If you awaitincr(key,undefined,true) first to load you can use the immediate (non-async) incrNow to update the value in memory without waiting for the file save to complete storing the new number.
setIncr(key, val)
Set counter for key to val-1 so next call to incr(key) returns val.
