139 lines
4.1 KiB
JavaScript
139 lines
4.1 KiB
JavaScript
const _ = require('lodash/fp')
|
|
const { format, isValid } = require('date-fns/fp')
|
|
const { utcToZonedTime } = require('date-fns-tz/fp')
|
|
|
|
const db = require('./db')
|
|
const logger = require('./logger')
|
|
const pgp = require('pg-promise')()
|
|
|
|
const getMachineName = require('./machine-loader').getMachineName
|
|
const NUM_RESULTS = 500
|
|
|
|
/**
|
|
* Get the latest log's timestamp
|
|
*
|
|
* @name getLastSeen
|
|
* @function
|
|
* @async
|
|
*
|
|
* @param {string} deviceId Machine id to get the last timestamp for
|
|
*
|
|
* @returns {date} Last timestamp
|
|
*/
|
|
function getLastSeen (deviceId) {
|
|
const sql = `select id, timestamp, serial from logs
|
|
where device_id=$1
|
|
order by timestamp desc, serial desc limit 1`
|
|
return db.oneOrNone(sql, [deviceId])
|
|
.then(log => log ? {timestamp: log.timestamp, serial: log.serial, id: log.id} : null)
|
|
}
|
|
|
|
/**
|
|
* Update logs in db
|
|
*
|
|
* @name update
|
|
* @function
|
|
* @async
|
|
*
|
|
* @param {string} deviceId Machine Id to which logs belong to
|
|
* @param {array} logLines Logs to be saved
|
|
*
|
|
* @returns {null}
|
|
*/
|
|
function update (deviceId, logLines) {
|
|
const cs = new pgp.helpers.ColumnSet([
|
|
'id', 'device_id', 'log_level', 'timestamp', 'serial', 'message'],
|
|
{table: 'logs'})
|
|
|
|
const logs = _.map(log => {
|
|
const formatted = {
|
|
id: log.id,
|
|
deviceId: deviceId,
|
|
message: log.msg,
|
|
logLevel: _.contains('error', _.lowerCase(log.msg)) ? 'error' : 'info',
|
|
timestamp: log.timestamp,
|
|
serial: log.serial || 0
|
|
}
|
|
return _.mapKeys(_.snakeCase, formatted)
|
|
}, logLines)
|
|
const sql = pgp.helpers.insert(logs, cs) + 'on conflict do nothing'
|
|
|
|
return db.none(sql)
|
|
}
|
|
|
|
function clearOldLogs () {
|
|
const sqls = `delete from logs
|
|
where timestamp < now() - interval '3 days';
|
|
delete from server_logs
|
|
where timestamp < now() - interval '3 days';`
|
|
return db.multi(sqls)
|
|
}
|
|
|
|
function getUnlimitedMachineLogs (deviceId, until = new Date().toISOString()) {
|
|
// Note: sql is a little confusing here, since timestamp is used both as a column
|
|
// and a reserved word, but it works.
|
|
const sql = `select id, log_level, timestamp, message from logs
|
|
where device_id=$1
|
|
and timestamp <= $2
|
|
and timestamp > (timestamp $2 - interval '2 days')
|
|
order by timestamp desc, serial desc`
|
|
|
|
return Promise.all([db.any(sql, [ deviceId, until ]), getMachineName(deviceId)])
|
|
.then(([logs, machineName]) => ({
|
|
logs: _.map(_.mapKeys(_.camelCase), logs),
|
|
currentMachine: {deviceId, name: machineName}
|
|
}))
|
|
}
|
|
|
|
function getMachineLogs (deviceId, until = new Date().toISOString(), limit = null, offset = 0) {
|
|
const sql = `select id, log_level, timestamp, message from logs
|
|
where device_id=$1
|
|
and timestamp <= $2
|
|
order by timestamp desc, serial desc
|
|
limit $3
|
|
offset $4`
|
|
|
|
return Promise.all([db.any(sql, [ deviceId, until, limit, offset ]), getMachineName(deviceId)])
|
|
.then(([logs, machineName]) => ({
|
|
logs: _.map(_.mapKeys(_.camelCase), logs),
|
|
currentMachine: {deviceId, name: machineName}
|
|
}))
|
|
}
|
|
|
|
function simpleGetMachineLogs (deviceId, from = new Date(0).toISOString(), until = new Date().toISOString(), limit = null, offset = 0) {
|
|
const sql = `select id, log_level, timestamp, message from logs
|
|
where device_id=$1
|
|
and timestamp >= $2
|
|
and timestamp <= $3
|
|
order by timestamp desc, serial desc
|
|
limit $4
|
|
offset $5`
|
|
|
|
return db.any(sql, [ deviceId, from, until, limit, offset ])
|
|
.then(_.map(_.mapKeys(_.camelCase)))
|
|
}
|
|
|
|
function logDateFormat (timezone, logs, fields) {
|
|
return _.map(log => {
|
|
const values = _.map(
|
|
field =>
|
|
{
|
|
if (_.isNil(log[field])) return null
|
|
if (!isValid(log[field])) {
|
|
logger.warn(`Tried to convert to ${timezone} timezone the value ${log[field]} and failed. Returning original value...`)
|
|
return log[field]
|
|
}
|
|
const date = utcToZonedTime(timezone, log[field])
|
|
return `${format('yyyy-MM-dd', date)}T${format('HH:mm:ss.SSS', date)}`
|
|
},
|
|
fields
|
|
)
|
|
const fieldsToOverride = _.zipObject(fields, values)
|
|
return {
|
|
...log,
|
|
...fieldsToOverride
|
|
}
|
|
}, logs)
|
|
}
|
|
|
|
module.exports = { getUnlimitedMachineLogs, getMachineLogs, simpleGetMachineLogs, update, getLastSeen, clearOldLogs, logDateFormat }
|