Create /logs/ api endpoint

This commit is contained in:
goga-m 2017-10-24 18:25:48 +03:00 committed by Josh Harvey
parent 43f578d311
commit 8ce22eca95
3 changed files with 156 additions and 146 deletions

View file

@ -191,6 +191,17 @@ app.get('/api/logs/:deviceId', (req, res, next) => {
.catch(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 * Endpoint for patching customer's data
* *

View file

@ -1,10 +1,24 @@
const _ = require('lodash/fp') const _ = require('lodash/fp')
const db = require('./db') 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 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) { function getLastSeen (deviceId) {
const sql = `select timestamp from logs const sql = `select timestamp from logs
where device_id=$1 where device_id=$1
@ -13,27 +27,35 @@ function getLastSeen (deviceId) {
.then(log => log ? log.timestamp : null) .then(log => log ? log.timestamp : null)
} }
function insert (log) { /**
console.log('inserting', log) * Update logs in db
const sql = `insert into logs *
(id, device_id, log_level, timestamp, message) values * @name update
($1, $2, $3, $4, $5) on conflict do nothing` * @function
return db.oneOrNone(sql, [log.id, log.deviceId, log.logLevel, log.timestamp, log.message]) * @async
} *
* @param {string} deviceId Machine Id to which logs belong to
* @param {array} logLines Logs to be saved
*
* @returns {null}
*/
function update (deviceId, logLines) { 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 => { const logs = _.map(log => {
return { const formatted = {
id: log.id, id: log.id,
deviceId: deviceId, deviceId: deviceId,
message: log.msg, message: log.msg,
logLevel: log.level, logLevel: log.level,
timestamp: log.timestamp timestamp: log.timestamp
} }
return _.mapKeys(_.snakeCase, formatted)
}, logLines) }, logLines)
// Batch save logs const sql = pgp.helpers.insert(logs, cs)
return Promise.all(_.map(insert, _.compact(logs))) return db.none(sql)
} }
/** /**
@ -47,51 +69,32 @@ function update (deviceId, logLines) {
* @returns {array} Array of logs for the requested machinej * @returns {array} Array of logs for the requested machinej
*/ */
function getMachineLogs (deviceId) { function getMachineLogs (deviceId) {
const sql = `select * from logs const sql = `select id, log_level, timestamp, message from logs
where device_id=$1 where device_id=$1
order by timestamp desc limit $2` order by timestamp desc limit $2`
return db.any(sql, [ deviceId, NUM_RESULTS ]) return Promise.all([db.any(sql, [ deviceId, NUM_RESULTS ]), getMachineName(deviceId)])
.then(_.map(camelize)) .then(([logs, machineName]) => ({
.then(logs => { logs: _.map(_.mapKeys(_.camelCase), logs),
return getMachineById(deviceId) currentMachine: {deviceId, name: machineName}
.then(currentMachine => { }))
return {
logs,
currentMachine
}
})
})
} }
/** /**
* Find machine by id * Given the machine id, get the machine name
* *
* @name getMachineById * @name getMachineName
* @function * @function
* @async * @async
* *
* @param {string} deviceId machine's id * @param {string} machineId machine id
* * @returns {string} machine name
* @returns {object} Found machine
*/ */
function getMachineById (deviceId) { function getMachineName (machineId) {
return machineLoader.getMachineNames().then(names => { return settingsLoader.loadRecentConfig()
return _.find({deviceId}, names) .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 } module.exports = { getMachineLogs, update, getLastSeen }

View file

@ -34135,9 +34135,9 @@ var _user$project$Logs_Types$Machine = F2(
function (a, b) { function (a, b) {
return {deviceId: a, name: b}; return {deviceId: a, name: b};
}); });
var _user$project$Logs_Types$Log = F5( var _user$project$Logs_Types$Log = F4(
function (a, b, c, d, e) { function (a, b, c, d) {
return {id: a, deviceId: b, timestamp: c, logLevel: d, message: e}; return {id: a, timestamp: b, logLevel: c, message: d};
}); });
var _user$project$Logs_Types$Logs = F2( var _user$project$Logs_Types$Logs = F2(
function (a, b) { 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), _elm_lang$core$Json_Decode$nullable(_elm_community$json_extra$Json_Decode_Extra$date),
A3( A3(
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required,
'deviceId', 'id',
_elm_lang$core$Json_Decode$nullable(_elm_lang$core$Json_Decode$string), _elm_lang$core$Json_Decode$string,
A3( _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$decode(_user$project$Logs_Types$Log)))));
_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))))));
var _user$project$Logs_Decoder$logsDecoder = A3( var _user$project$Logs_Decoder$logsDecoder = A3(
_NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required, _NoRedInk$elm_decode_pipeline$Json_Decode_Pipeline$required,
'currentMachine', 'currentMachine',
@ -35696,45 +35692,45 @@ var _user$project$Logs_View$logsView = function (logs) {
{ {
ctor: '::', ctor: '::',
_0: A2( _0: A2(
_elm_lang$html$Html$h2, _elm_lang$html$Html$table,
{ctor: '[]'},
{ {
ctor: '::', 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: '[]'}
}), },
_1: { {
ctor: '::', ctor: '::',
_0: A2( _0: A2(
_elm_lang$html$Html$table, _elm_lang$html$Html$thead,
{ {ctor: '[]'},
ctor: '::', {
_0: _user$project$Css_Admin$class( ctor: '::',
{ _0: A2(
ctor: '::', _elm_lang$html$Html$tr,
_0: _user$project$Css_Classes$TxTable, {ctor: '[]'},
_1: {ctor: '[]'} {
}), ctor: '::',
_1: {ctor: '[]'} _0: A2(
}, _elm_lang$html$Html$td,
{ {ctor: '[]'},
ctor: '::', {
_0: A2( ctor: '::',
_elm_lang$html$Html$thead, _0: _elm_lang$html$Html$text('Date'),
{ctor: '[]'}, _1: {ctor: '[]'}
{ }),
ctor: '::', _1: {
_0: A2(
_elm_lang$html$Html$tr,
{ctor: '[]'},
{
ctor: '::', ctor: '::',
_0: A2( _0: A2(
_elm_lang$html$Html$td, _elm_lang$html$Html$td,
{ctor: '[]'}, {ctor: '[]'},
{ {
ctor: '::', ctor: '::',
_0: _elm_lang$html$Html$text('Date'), _0: _elm_lang$html$Html$text('Level'),
_1: {ctor: '[]'} _1: {ctor: '[]'}
}), }),
_1: { _1: {
@ -35744,36 +35740,25 @@ var _user$project$Logs_View$logsView = function (logs) {
{ctor: '[]'}, {ctor: '[]'},
{ {
ctor: '::', ctor: '::',
_0: _elm_lang$html$Html$text('Level'), _0: _elm_lang$html$Html$text('Message'),
_1: {ctor: '[]'} _1: {ctor: '[]'}
}), }),
_1: { _1: {ctor: '[]'}
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: '::',
_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: {
_1: {ctor: '[]'} 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) { var _user$project$Logs_View$logs = function (model) {
@ -35786,7 +35771,7 @@ var _user$project$Logs_View$logs = function (model) {
{ctor: '[]'}); {ctor: '[]'});
case 'Loading': case 'Loading':
return A2( return A2(
_elm_lang$html$Html$h2, _elm_lang$html$Html$div,
{ctor: '[]'}, {ctor: '[]'},
{ {
ctor: '::', ctor: '::',
@ -35884,37 +35869,26 @@ var _user$project$Logs_View$machinesView = function (machines) {
{ {
ctor: '::', ctor: '::',
_0: A2( _0: A2(
_elm_lang$html$Html$h2, _elm_lang$html$Html$div,
{ctor: '[]'},
{ {
ctor: '::', 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: '[]'}
}), }),
_1: { _1: {ctor: '[]'}
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: '[]'}
}
}); });
}; };
var _user$project$Logs_View$machines = function (model) { var _user$project$Logs_View$machines = function (model) {
@ -35927,7 +35901,7 @@ var _user$project$Logs_View$machines = function (model) {
{ctor: '[]'}); {ctor: '[]'});
case 'Loading': case 'Loading':
return A2( return A2(
_elm_lang$html$Html$h2, _elm_lang$html$Html$div,
{ctor: '[]'}, {ctor: '[]'},
{ {
ctor: '::', ctor: '::',
@ -35999,8 +35973,19 @@ var _user$project$Logs_View$view = function (model) {
}, },
{ {
ctor: '::', ctor: '::',
_0: _user$project$Logs_View$machines(model), _0: A2(
_1: {ctor: '[]'} _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: { _1: {
ctor: '::', ctor: '::',
@ -36018,8 +36003,19 @@ var _user$project$Logs_View$view = function (model) {
}, },
{ {
ctor: '::', ctor: '::',
_0: _user$project$Logs_View$logs(model), _0: A2(
_1: {ctor: '[]'} _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: '[]'} _1: {ctor: '[]'}
} }