Create /logs/ api endpoint
This commit is contained in:
parent
43f578d311
commit
8ce22eca95
3 changed files with 156 additions and 146 deletions
|
|
@ -191,6 +191,17 @@ app.get('/api/logs/:deviceId', (req, res, next) => {
|
|||
.catch(next)
|
||||
})
|
||||
|
||||
app.get('/api/logs', (req, res, next) => {
|
||||
return machineLoader.getMachines()
|
||||
.then(machines => {
|
||||
const firstMachine = _.first(machines)
|
||||
if (!firstMachine) return res.status(404).send({Error: 'No machines'})
|
||||
return logs.getMachineLogs(firstMachine.deviceId)
|
||||
.then(r => res.send(r))
|
||||
})
|
||||
.catch(next)
|
||||
})
|
||||
|
||||
/**
|
||||
* Endpoint for patching customer's data
|
||||
*
|
||||
|
|
|
|||
97
lib/logs.js
97
lib/logs.js
|
|
@ -1,10 +1,24 @@
|
|||
const _ = require('lodash/fp')
|
||||
|
||||
const db = require('./db')
|
||||
const machineLoader = require('./machine-loader')
|
||||
const pgp = require('pg-promise')()
|
||||
|
||||
const settingsLoader = require('./settings-loader')
|
||||
const configManager = require('./config-manager')
|
||||
|
||||
const NUM_RESULTS = 1000
|
||||
|
||||
/**
|
||||
* 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 timestamp from logs
|
||||
where device_id=$1
|
||||
|
|
@ -13,27 +27,35 @@ function getLastSeen (deviceId) {
|
|||
.then(log => log ? log.timestamp : null)
|
||||
}
|
||||
|
||||
function insert (log) {
|
||||
console.log('inserting', log)
|
||||
const sql = `insert into logs
|
||||
(id, device_id, log_level, timestamp, message) values
|
||||
($1, $2, $3, $4, $5) on conflict do nothing`
|
||||
return db.oneOrNone(sql, [log.id, log.deviceId, log.logLevel, log.timestamp, log.message])
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// Prepare logs to update
|
||||
const cs = new pgp.helpers.ColumnSet([
|
||||
'id', 'device_id', 'log_level', 'timestamp', 'message'],
|
||||
{table: 'logs'})
|
||||
|
||||
const logs = _.map(log => {
|
||||
return {
|
||||
const formatted = {
|
||||
id: log.id,
|
||||
deviceId: deviceId,
|
||||
message: log.msg,
|
||||
logLevel: log.level,
|
||||
timestamp: log.timestamp
|
||||
}
|
||||
return _.mapKeys(_.snakeCase, formatted)
|
||||
}, logLines)
|
||||
// Batch save logs
|
||||
return Promise.all(_.map(insert, _.compact(logs)))
|
||||
const sql = pgp.helpers.insert(logs, cs)
|
||||
return db.none(sql)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -47,51 +69,32 @@ function update (deviceId, logLines) {
|
|||
* @returns {array} Array of logs for the requested machinej
|
||||
*/
|
||||
function getMachineLogs (deviceId) {
|
||||
const sql = `select * from logs
|
||||
const sql = `select id, log_level, timestamp, message from logs
|
||||
where device_id=$1
|
||||
order by timestamp desc limit $2`
|
||||
return db.any(sql, [ deviceId, NUM_RESULTS ])
|
||||
.then(_.map(camelize))
|
||||
.then(logs => {
|
||||
return getMachineById(deviceId)
|
||||
.then(currentMachine => {
|
||||
return {
|
||||
logs,
|
||||
currentMachine
|
||||
}
|
||||
})
|
||||
})
|
||||
return Promise.all([db.any(sql, [ deviceId, NUM_RESULTS ]), getMachineName(deviceId)])
|
||||
.then(([logs, machineName]) => ({
|
||||
logs: _.map(_.mapKeys(_.camelCase), logs),
|
||||
currentMachine: {deviceId, name: machineName}
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Find machine by id
|
||||
* Given the machine id, get the machine name
|
||||
*
|
||||
* @name getMachineById
|
||||
* @name getMachineName
|
||||
* @function
|
||||
* @async
|
||||
*
|
||||
* @param {string} deviceId machine's id
|
||||
*
|
||||
* @returns {object} Found machine
|
||||
* @param {string} machineId machine id
|
||||
* @returns {string} machine name
|
||||
*/
|
||||
function getMachineById (deviceId) {
|
||||
return machineLoader.getMachineNames().then(names => {
|
||||
return _.find({deviceId}, names)
|
||||
function getMachineName (machineId) {
|
||||
return settingsLoader.loadRecentConfig()
|
||||
.then(config => {
|
||||
const machineScoped = configManager.machineScoped(machineId, config)
|
||||
return machineScoped.machineName
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Camelize log fields
|
||||
* Note: return null if log is undefined
|
||||
*
|
||||
* @name camelize
|
||||
* @function
|
||||
*
|
||||
* @param {object} log Log with snake_case fields
|
||||
* @returns {object} Camelized Log object
|
||||
*/
|
||||
function camelize (log) {
|
||||
return log ? _.mapKeys(_.camelCase, log) : null
|
||||
}
|
||||
|
||||
module.exports = { getMachineLogs, update, getLastSeen }
|
||||
|
|
|
|||
194
public/elm.js
194
public/elm.js
|
|
@ -34135,9 +34135,9 @@ var _user$project$Logs_Types$Machine = F2(
|
|||
function (a, b) {
|
||||
return {deviceId: a, name: b};
|
||||
});
|
||||
var _user$project$Logs_Types$Log = F5(
|
||||
function (a, b, c, d, e) {
|
||||
return {id: a, deviceId: b, timestamp: c, logLevel: d, message: e};
|
||||
var _user$project$Logs_Types$Log = F4(
|
||||
function (a, b, c, d) {
|
||||
return {id: a, timestamp: b, logLevel: c, message: d};
|
||||
});
|
||||
var _user$project$Logs_Types$Logs = F2(
|
||||
function (a, b) {
|
||||
|
|
@ -35547,13 +35547,9 @@ var _user$project$Logs_Decoder$logDecoder = A3(
|
|||
_elm_lang$core$Json_Decode$nullable(_elm_community$json_extra$Json_Decode_Extra$date),
|
||||
A3(
|
||||
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required,
|
||||
'deviceId',
|
||||
_elm_lang$core$Json_Decode$nullable(_elm_lang$core$Json_Decode$string),
|
||||
A3(
|
||||
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required,
|
||||
'id',
|
||||
_elm_lang$core$Json_Decode$string,
|
||||
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$decode(_user$project$Logs_Types$Log))))));
|
||||
'id',
|
||||
_elm_lang$core$Json_Decode$string,
|
||||
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$decode(_user$project$Logs_Types$Log)))));
|
||||
var _user$project$Logs_Decoder$logsDecoder = A3(
|
||||
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required,
|
||||
'currentMachine',
|
||||
|
|
@ -35696,45 +35692,45 @@ var _user$project$Logs_View$logsView = function (logs) {
|
|||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$h2,
|
||||
{ctor: '[]'},
|
||||
_elm_lang$html$Html$table,
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Logs'),
|
||||
_0: _user$project$Css_Admin$class(
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Css_Classes$TxTable,
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$table,
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Css_Admin$class(
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Css_Classes$TxTable,
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$thead,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$tr,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$thead,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$tr,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$td,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Date'),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$td,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Date'),
|
||||
_0: _elm_lang$html$Html$text('Level'),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
|
|
@ -35744,36 +35740,25 @@ var _user$project$Logs_View$logsView = function (logs) {
|
|||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Level'),
|
||||
_0: _elm_lang$html$Html$text('Message'),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$td,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Message'),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$tbody,
|
||||
{ctor: '[]'},
|
||||
A2(_elm_lang$core$List$map, _user$project$Logs_View$rowView, logs.logs)),
|
||||
}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$tbody,
|
||||
{ctor: '[]'},
|
||||
A2(_elm_lang$core$List$map, _user$project$Logs_View$rowView, logs.logs)),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
});
|
||||
};
|
||||
var _user$project$Logs_View$logs = function (model) {
|
||||
|
|
@ -35786,7 +35771,7 @@ var _user$project$Logs_View$logs = function (model) {
|
|||
{ctor: '[]'});
|
||||
case 'Loading':
|
||||
return A2(
|
||||
_elm_lang$html$Html$h2,
|
||||
_elm_lang$html$Html$div,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
|
|
@ -35884,37 +35869,26 @@ var _user$project$Logs_View$machinesView = function (machines) {
|
|||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$h2,
|
||||
{ctor: '[]'},
|
||||
_elm_lang$html$Html$div,
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Machines'),
|
||||
_0: _user$project$Css_Admin$class(
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Css_Classes$TxTable,
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$ul,
|
||||
{ctor: '[]'},
|
||||
A2(_elm_lang$core$List$map, _user$project$Logs_View$machineItemView, machines)),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$div,
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Css_Admin$class(
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Css_Classes$TxTable,
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$ul,
|
||||
{ctor: '[]'},
|
||||
A2(_elm_lang$core$List$map, _user$project$Logs_View$machineItemView, machines)),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
_1: {ctor: '[]'}
|
||||
});
|
||||
};
|
||||
var _user$project$Logs_View$machines = function (model) {
|
||||
|
|
@ -35927,7 +35901,7 @@ var _user$project$Logs_View$machines = function (model) {
|
|||
{ctor: '[]'});
|
||||
case 'Loading':
|
||||
return A2(
|
||||
_elm_lang$html$Html$h2,
|
||||
_elm_lang$html$Html$div,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
|
|
@ -35999,8 +35973,19 @@ var _user$project$Logs_View$view = function (model) {
|
|||
},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Logs_View$machines(model),
|
||||
_1: {ctor: '[]'}
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$h2,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Machines'),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: _user$project$Logs_View$machines(model),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
|
|
@ -36018,8 +36003,19 @@ var _user$project$Logs_View$view = function (model) {
|
|||
},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _user$project$Logs_View$logs(model),
|
||||
_1: {ctor: '[]'}
|
||||
_0: A2(
|
||||
_elm_lang$html$Html$h2,
|
||||
{ctor: '[]'},
|
||||
{
|
||||
ctor: '::',
|
||||
_0: _elm_lang$html$Html$text('Logs'),
|
||||
_1: {ctor: '[]'}
|
||||
}),
|
||||
_1: {
|
||||
ctor: '::',
|
||||
_0: _user$project$Logs_View$logs(model),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
}),
|
||||
_1: {ctor: '[]'}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue