Skip to content

Commit

Permalink
feat(app): Log tracebacks from failed RPC calls
Browse files Browse the repository at this point in the history
Closes #1841
  • Loading branch information
mcous committed Jul 10, 2018
1 parent 619e2d9 commit 0dcbbb5
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 7 deletions.
7 changes: 5 additions & 2 deletions api/opentrons/server/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,11 @@ async def make_call(self, func, token):
line_no = 'unknown'
finally:
response['$']['status'] = 'error'
call_result = '{0} [line {1}]: {2}'.format(
e.__class__.__name__, line_no, str(e))
call_result = {
'message': '{0} [line {1}]: {2}'.format(
e.__class__.__name__, line_no, str(e)),
'traceback': traceback.format_exc()
}
finally:
response['data'] = call_result
return response
Expand Down
19 changes: 18 additions & 1 deletion app/src/robot/api-client/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
// robot api client redux middleware
// wraps the api client worker to handle API side effects in a different thread

import createLogger from '../../logger'
import Worker from './worker'

const log = createLogger(__filename)

export default function apiClientMiddleware () {
const worker = new Worker()

return (store) => {
const {getState, dispatch} = store

worker.onmessage = function handleWorkerMessage (event) {
dispatch(event.data)
const action = event.data

// log error actions
if (action && action.payload) {
const error = action.error === true
? action.payload
: action.payload.error

if (error) {
log.warn('Error response from robot', {action})
if (error.traceback) log.warn(error.traceback)
}
}

dispatch(action)
}

// initialize worker
Expand Down
6 changes: 3 additions & 3 deletions app/src/rpc/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ class RpcContext extends EventEmitter {
return new Promise((resolve, reject) => {
let timeout

const handleError = (reason) => {
const handleError = (reason, traceback) => {
cleanup()
reject(new RemoteError(reason, name, args))
reject(new RemoteError(reason, name, args, traceback))
}

const handleFailure = (result) => handleError(result)
const handleFailure = (res) => handleError(res.message, res.traceback)
const handleNack = (reason) => handleError(`Received NACK with ${reason}`)

const handleAck = () => {
Expand Down
3 changes: 2 additions & 1 deletion app/src/rpc/remote-error.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// remote call error object
export default class RemoteError extends Error {
constructor (message, methodName, args) {
constructor (message, methodName, args, traceback) {
super(message)
this.name = this.constructor.name
this.methodName = methodName
this.args = args
this.traceback = traceback
}
}

0 comments on commit 0dcbbb5

Please sign in to comment.