mirror of
https://github.com/status-im/embark-area-51.git
synced 2025-02-12 23:26:39 +00:00
Merge pull request #19 from status-im/features/process-logs
Add logs for the processes
This commit is contained in:
commit
eeafa56e93
@ -10,7 +10,7 @@
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2017,
|
||||
"ecmaVersion": 2018,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
|
@ -6,6 +6,10 @@ export const RECEIVE_ACCOUNTS_ERROR = 'RECEIVE_ACCOUNTS_ERROR';
|
||||
export const FETCH_PROCESSES = 'FETCH_PROCESSES';
|
||||
export const RECEIVE_PROCESSES = 'RECEIVE_PROCESSES';
|
||||
export const RECEIVE_PROCESSES_ERROR = 'RECEIVE_PROCESSES_ERROR';
|
||||
// Process logs
|
||||
export const FETCH_PROCESS_LOGS = 'FETCH_PROCESS_LOGS';
|
||||
export const RECEIVE_PROCESS_LOGS = 'RECEIVE_PROCESS_LOGS';
|
||||
export const RECEIVE_PROCESS_LOGS_ERROR = 'RECEIVE_PROCESS_LOGS_ERROR';
|
||||
// Blocks
|
||||
export const FETCH_BLOCKS = 'FETCH_BLOCKS';
|
||||
export const RECEIVE_BLOCKS = 'RECEIVE_BLOCKS';
|
||||
@ -47,9 +51,32 @@ export function receiveProcesses(processes) {
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveProcessesError() {
|
||||
export function receiveProcessesError(error) {
|
||||
return {
|
||||
type: RECEIVE_PROCESSES_ERROR
|
||||
type: RECEIVE_PROCESSES_ERROR,
|
||||
error
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchProcessLogs(processName) {
|
||||
return {
|
||||
type: FETCH_PROCESS_LOGS,
|
||||
processName
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveProcessLogs(processName, logs) {
|
||||
return {
|
||||
type: RECEIVE_PROCESS_LOGS,
|
||||
processName,
|
||||
logs
|
||||
};
|
||||
}
|
||||
|
||||
export function receiveProcessLogsError(error) {
|
||||
return {
|
||||
type: RECEIVE_PROCESS_LOGS_ERROR,
|
||||
error
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
import axios from "axios";
|
||||
import constants from '../constants';
|
||||
|
||||
const BASE_URL = 'http://localhost:8000/embark-api';
|
||||
|
||||
export function fetchAccounts() {
|
||||
return axios.get(`${BASE_URL}/blockchain/accounts`);
|
||||
return axios.get(constants.httpEndpoint + '/blockchain/accounts');
|
||||
}
|
||||
|
||||
export function fetchBlocks(from) {
|
||||
@ -15,5 +16,9 @@ export function fetchTransactions(blockFrom) {
|
||||
}
|
||||
|
||||
export function fetchProcesses() {
|
||||
return axios.get(`${BASE_URL}/processes`);
|
||||
return axios.get(constants.httpEndpoint + '/processes');
|
||||
}
|
||||
|
||||
export function fetchProcessLogs(processName) {
|
||||
return axios.get(`${constants.httpEndpoint}/process-logs/${processName}`);
|
||||
}
|
||||
|
86
embark-ui/src/components/Process.js
Normal file
86
embark-ui/src/components/Process.js
Normal file
@ -0,0 +1,86 @@
|
||||
import React, {Component} from 'react';
|
||||
import connect from "react-redux/es/connect/connect";
|
||||
import {fetchProcessLogs} from "../actions";
|
||||
import constants from '../constants';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Process extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
logs: []
|
||||
};
|
||||
this.gotOriginalLogs = false;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const self = this;
|
||||
|
||||
this.props.fetchProcessLogs(self.props.processName);
|
||||
|
||||
this.ws = new WebSocket(constants.wsEndpoint + '/process-logs/' + self.props.processName);
|
||||
|
||||
this.ws.onmessage = function(evt) {
|
||||
const log = JSON.parse(evt.data);
|
||||
const logs = self.state.logs;
|
||||
logs.push(log);
|
||||
self.setState({
|
||||
logs
|
||||
});
|
||||
};
|
||||
|
||||
this.ws.onclose = function() {
|
||||
console.log(self.props.processName + "Log process connection is closed");
|
||||
};
|
||||
|
||||
window.onbeforeunload = function(_event) {
|
||||
this.ws.close();
|
||||
};
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, _nextState) {
|
||||
if (!this.gotOriginalLogs && nextProps.logs && nextProps.logs[this.props.processName]) {
|
||||
const logs = nextProps.logs[this.props.processName].concat(this.state.logs);
|
||||
this.gotOriginalLogs = true;
|
||||
this.setState({
|
||||
logs
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.ws.close();
|
||||
this.ws = null;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
State: {this.props.state}
|
||||
<div className="logs">
|
||||
{
|
||||
this.state.logs.map((item, i) => <p key={i} className={item.logLevel}>{item.msg_clear || item.msg}</p>)
|
||||
}
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
|
||||
Process.propTypes = {
|
||||
processName: PropTypes.string.isRequired,
|
||||
state: PropTypes.string.isRequired,
|
||||
fetchProcessLogs: PropTypes.func,
|
||||
logs: PropTypes.object
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {logs: state.processes.logs};
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
fetchProcessLogs
|
||||
}
|
||||
)(Process);
|
4
embark-ui/src/constants.json
Normal file
4
embark-ui/src/constants.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"httpEndpoint": "http://localhost:8000/embark-api",
|
||||
"wsEndpoint": "ws://localhost:8000/embark-api"
|
||||
}
|
@ -7,6 +7,7 @@ import {fetchProcesses} from '../actions';
|
||||
import Loading from '../components/Loading';
|
||||
|
||||
import "./css/processContainer.css";
|
||||
import Process from "../components/Process";
|
||||
|
||||
class ProcessesContainer extends Component {
|
||||
componentDidMount() {
|
||||
@ -19,22 +20,21 @@ class ProcessesContainer extends Component {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (processes.error) {
|
||||
return (
|
||||
<h1>
|
||||
<i>Error loading processes: {processes.error.message || processes.error}</i>
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
const processNames = Object.keys(processes.data);
|
||||
return (
|
||||
<div className="processes-container">
|
||||
<Tabs initialTab={processNames[0]}>
|
||||
{processes.error && <h1>
|
||||
<i>Error: {processes.error.message || processes.error}</i>
|
||||
</h1>}
|
||||
|
||||
{processNames && processNames.length && <Tabs initialTab={processNames[0]}>
|
||||
{processNames.map(processName => {
|
||||
return (<Tab key={processName} title={processName}>State: {processes.data[processName].state}</Tab>);
|
||||
return (<Tab key={processName} title={processName}>
|
||||
<Process processName={processName} state={processes.data[processName].state}/>
|
||||
</Tab>);
|
||||
})}
|
||||
</Tabs>
|
||||
</Tabs>}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -2,3 +2,26 @@
|
||||
.processes-container .nav-link {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.processes-container .logs {
|
||||
margin: 10px 0;
|
||||
background-color: #333333;
|
||||
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.processes-container .logs .error {
|
||||
color: #dc3546;
|
||||
}
|
||||
.processes-container .logs .warn {
|
||||
color: #fec107;
|
||||
}
|
||||
.processes-container .logs .debug {
|
||||
color: #b7c1cc;
|
||||
}
|
||||
.processes-container .logs .trace {
|
||||
color: #8f98a2;
|
||||
}
|
||||
|
@ -1,11 +1,21 @@
|
||||
import {RECEIVE_PROCESSES, RECEIVE_PROCESSES_ERROR} from "../actions";
|
||||
import {RECEIVE_PROCESSES, RECEIVE_PROCESSES_ERROR, RECEIVE_PROCESS_LOGS, RECEIVE_PROCESS_LOGS_ERROR} from "../actions";
|
||||
|
||||
export default function processes(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case RECEIVE_PROCESSES:
|
||||
return Object.assign({}, state, {data: action.processes.data});
|
||||
case RECEIVE_PROCESSES_ERROR:
|
||||
return Object.assign({}, state, {error: true});
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
case RECEIVE_PROCESS_LOGS:
|
||||
return {
|
||||
...state,
|
||||
logs: {
|
||||
...state.logs,
|
||||
[action.processName]: action.logs.data
|
||||
}
|
||||
};
|
||||
case RECEIVE_PROCESS_LOGS_ERROR:
|
||||
return Object.assign({}, state, {error: action.error});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ export function *fetchProcesses() {
|
||||
const processes = yield call(api.fetchProcesses);
|
||||
yield put(actions.receiveProcesses(processes));
|
||||
} catch (e) {
|
||||
yield put(actions.receiveProcessesError());
|
||||
yield put(actions.receiveProcessesError(e));
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,10 +54,24 @@ export function *watchFetchProcesses() {
|
||||
yield takeEvery(actions.FETCH_PROCESSES, fetchProcesses);
|
||||
}
|
||||
|
||||
export function *fetchProcessLogs(action) {
|
||||
try {
|
||||
const logs = yield call(api.fetchProcessLogs, action.processName);
|
||||
yield put(actions.receiveProcessLogs(action.processName, logs));
|
||||
} catch (e) {
|
||||
yield put(actions.receiveProcessLogsError(e));
|
||||
}
|
||||
}
|
||||
|
||||
export function *watchFetchProcessLogs() {
|
||||
yield takeEvery(actions.FETCH_PROCESS_LOGS, fetchProcessLogs);
|
||||
}
|
||||
|
||||
export default function *root() {
|
||||
yield all([
|
||||
fork(watchFetchAccounts),
|
||||
fork(watchFetchProcesses),
|
||||
fork(watchFetchProcessLogs),
|
||||
fork(watchFetchBlocks),
|
||||
fork(watchFetchTransactions)
|
||||
]);
|
||||
|
@ -212,8 +212,9 @@ Plugin.prototype.registerActionForEvent = function(eventName, cb) {
|
||||
|
||||
Plugin.prototype.registerAPICall = function(method, endpoint, cb) {
|
||||
console.dir("registerAPICall " + method + " " + endpoint);
|
||||
this.apiCalls.push({method: method, endpoint: endpoint, cb: cb});
|
||||
this.apiCalls.push({method, endpoint, cb});
|
||||
this.addPluginType('apiCalls');
|
||||
this.events.emit('plugins:register:api', {method, endpoint, cb});
|
||||
};
|
||||
|
||||
Plugin.prototype.runFilePipeline = function() {
|
||||
|
@ -21,6 +21,7 @@ class ProcessLauncher {
|
||||
this.silent = options.silent;
|
||||
this.exitCallback = options.exitCallback;
|
||||
this.embark = options.embark;
|
||||
this.logs = [];
|
||||
|
||||
this.subscriptions = {};
|
||||
this._subscribeToMessages();
|
||||
@ -54,20 +55,29 @@ class ProcessLauncher {
|
||||
|
||||
_registerAsPlugin() {
|
||||
const self = this;
|
||||
const apiRoute = '/embark-api/process-logs/' + self.name;
|
||||
self.embark.registerAPICall(
|
||||
'ws',
|
||||
'/embark-api/process-logs/' + self.name,
|
||||
apiRoute,
|
||||
(ws, _req) => {
|
||||
self.events.on('log-' + self.name, function(logLevel, msg) {
|
||||
self.events.on('process-log-' + self.name, function(logLevel, msg) {
|
||||
ws.send(JSON.stringify({msg, msg_clear: msg.stripColors, logLevel}), () => {});
|
||||
});
|
||||
}
|
||||
);
|
||||
self.embark.registerAPICall(
|
||||
'get',
|
||||
apiRoute,
|
||||
(req, res) => {
|
||||
res.send(JSON.stringify(self.logs));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Translates logs from the child process to the logger
|
||||
_handleLog(msg) {
|
||||
this.events.emit('log-' + this.name, msg.type, msg.message);
|
||||
this.events.emit('process-log-' + this.name, msg.type, msg.message);
|
||||
this.logs.push({msg: msg.message, msg_clear: msg.message.stripColors, logLevel: msg.logLevel});
|
||||
if (this.silent && msg.type !== 'error') {
|
||||
return;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ class BlockchainProcessLauncher {
|
||||
this.blockchainConfig = options.blockchainConfig;
|
||||
this.locale = options.locale;
|
||||
this.isDev = options.isDev;
|
||||
this.embark = options.embark;
|
||||
}
|
||||
|
||||
processEnded(code) {
|
||||
@ -21,16 +22,17 @@ class BlockchainProcessLauncher {
|
||||
this.logger.info(__('Starting Blockchain node in another process').cyan);
|
||||
|
||||
this.blockchainProcess = new ProcessLauncher({
|
||||
name: 'blockchain',
|
||||
modulePath: utils.joinPath(__dirname, './blockchainProcess.js'),
|
||||
logger: this.logger,
|
||||
events: this.events,
|
||||
embark: this.embark,
|
||||
silent: this.logger.logLevel !== 'trace',
|
||||
exitCallback: this.processEnded.bind(this)
|
||||
});
|
||||
this.blockchainProcess.send({
|
||||
action: constants.blockchain.init, options: {
|
||||
blockchainConfig: this.blockchainConfig,
|
||||
//client: this.client,
|
||||
// TODO: assume for now it's geth
|
||||
client: 'geth',
|
||||
env: this.env,
|
||||
@ -45,7 +47,7 @@ class BlockchainProcessLauncher {
|
||||
});
|
||||
|
||||
this.blockchainProcess.once('result', constants.blockchain.blockchainExit, () => {
|
||||
// telle everyone that our blockchain process (ie geth) died
|
||||
// tell everyone that our blockchain process (ie geth) died
|
||||
this.events.emit(constants.blockchain.blockchainExit);
|
||||
|
||||
// then kill off the blockchain process
|
||||
|
@ -66,7 +66,8 @@ class BlockchainModule {
|
||||
normalizeInput: utils.normalizeInput,
|
||||
blockchainConfig: self.blockchainConfig,
|
||||
locale: self.locale,
|
||||
isDev: self.isDev
|
||||
isDev: self.isDev,
|
||||
embark: this.embark
|
||||
});
|
||||
|
||||
blockchainProcess.startBlockchainNode();
|
||||
|
@ -27,11 +27,15 @@ class Swarm {
|
||||
return;
|
||||
}
|
||||
|
||||
this.events.request('processes:register', 'swarm', (cb) => {
|
||||
self.startProcess(cb);
|
||||
});
|
||||
|
||||
this.bzz = new Web3Bzz(this.providerUrl);
|
||||
|
||||
this.setServiceCheck();
|
||||
this.addProviderToEmbarkJS();
|
||||
this.startProcess(() => {});
|
||||
this.events.request("processes:launch", "swarm", () => {});
|
||||
this.registerUploadCommand();
|
||||
|
||||
this._checkService((err) => {
|
||||
@ -88,7 +92,8 @@ class Swarm {
|
||||
events: self.events,
|
||||
storageConfig: self.storageConfig,
|
||||
webServerConfig: self.webServerConfig,
|
||||
blockchainConfig: self.blockchainConfig
|
||||
blockchainConfig: self.blockchainConfig,
|
||||
embark: self.embark
|
||||
});
|
||||
self.logger.trace(`Storage module: Launching swarm process...`);
|
||||
return storageProcessesLauncher.launchProcess('swarm', callback);
|
||||
|
@ -48,6 +48,11 @@ class Server {
|
||||
}
|
||||
}
|
||||
|
||||
this.events.on('plugins:register:api', (apiCall) => {
|
||||
console.dir("adding " + apiCall.method + " " + apiCall.endpoint);
|
||||
app[apiCall.method].apply(app, [apiCall.endpoint, apiCall.cb]);
|
||||
});
|
||||
|
||||
app.get('/embark/*', function (req, res) {
|
||||
self.logger.trace('webserver> GET ' + req.path);
|
||||
res.sendFile(path.join(__dirname, '../../../embark-ui/build', 'index.html'));
|
||||
|
Loading…
x
Reference in New Issue
Block a user