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)
})
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
*

View file

@ -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 }

View file

@ -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: '[]'}
}