cmd, dashboard, log: log collection and exploration (#17097)
* cmd, dashboard, internal, log, node: logging feature * cmd, dashboard, internal, log: requested changes * dashboard, vendor: gofmt, govendor, use vendored file watcher * dashboard, log: gofmt -s -w, goimports * dashboard, log: gosimple
This commit is contained in:
committed by
Péter Szilágyi
parent
2eedbe799f
commit
a9835c1816
@ -24,6 +24,7 @@ import Header from './Header';
|
||||
import Body from './Body';
|
||||
import {MENU} from '../common';
|
||||
import type {Content} from '../types/content';
|
||||
import {inserter as logInserter} from './Logs';
|
||||
|
||||
// deepUpdate updates an object corresponding to the given update data, which has
|
||||
// the shape of the same structure as the original object. updater also has the same
|
||||
@ -75,8 +76,11 @@ const appender = <T>(limit: number, mapper = replacer) => (update: Array<T>, pre
|
||||
...update.map(sample => mapper(sample)),
|
||||
].slice(-limit);
|
||||
|
||||
// defaultContent is the initial value of the state content.
|
||||
const defaultContent: Content = {
|
||||
// defaultContent returns the initial value of the state content. Needs to be a function in order to
|
||||
// instantiate the object again, because it is used by the state, and isn't automatically cleaned
|
||||
// when a new connection is established. The state is mutated during the update in order to avoid
|
||||
// the execution of unnecessary operations (e.g. copy of the log array).
|
||||
const defaultContent: () => Content = () => ({
|
||||
general: {
|
||||
version: null,
|
||||
commit: null,
|
||||
@ -95,10 +99,14 @@ const defaultContent: Content = {
|
||||
diskRead: [],
|
||||
diskWrite: [],
|
||||
},
|
||||
logs: {
|
||||
log: [],
|
||||
logs: {
|
||||
chunks: [],
|
||||
endTop: false,
|
||||
endBottom: true,
|
||||
topChanged: 0,
|
||||
bottomChanged: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// updaters contains the state updater functions for each path of the state.
|
||||
//
|
||||
@ -122,9 +130,7 @@ const updaters = {
|
||||
diskRead: appender(200),
|
||||
diskWrite: appender(200),
|
||||
},
|
||||
logs: {
|
||||
log: appender(200),
|
||||
},
|
||||
logs: logInserter(5),
|
||||
};
|
||||
|
||||
// styles contains the constant styles of the component.
|
||||
@ -151,10 +157,11 @@ export type Props = {
|
||||
};
|
||||
|
||||
type State = {
|
||||
active: string, // active menu
|
||||
sideBar: boolean, // true if the sidebar is opened
|
||||
content: Content, // the visualized data
|
||||
shouldUpdate: Object, // labels for the components, which need to re-render based on the incoming message
|
||||
active: string, // active menu
|
||||
sideBar: boolean, // true if the sidebar is opened
|
||||
content: Content, // the visualized data
|
||||
shouldUpdate: Object, // labels for the components, which need to re-render based on the incoming message
|
||||
server: ?WebSocket,
|
||||
};
|
||||
|
||||
// Dashboard is the main component, which renders the whole page, makes connection with the server and
|
||||
@ -165,8 +172,9 @@ class Dashboard extends Component<Props, State> {
|
||||
this.state = {
|
||||
active: MENU.get('home').id,
|
||||
sideBar: true,
|
||||
content: defaultContent,
|
||||
content: defaultContent(),
|
||||
shouldUpdate: {},
|
||||
server: null,
|
||||
};
|
||||
}
|
||||
|
||||
@ -181,7 +189,7 @@ class Dashboard extends Component<Props, State> {
|
||||
// PROD is defined by webpack.
|
||||
const server = new WebSocket(`${((window.location.protocol === 'https:') ? 'wss://' : 'ws://')}${PROD ? window.location.host : 'localhost:8080'}/api`);
|
||||
server.onopen = () => {
|
||||
this.setState({content: defaultContent, shouldUpdate: {}});
|
||||
this.setState({content: defaultContent(), shouldUpdate: {}, server});
|
||||
};
|
||||
server.onmessage = (event) => {
|
||||
const msg: $Shape<Content> = JSON.parse(event.data);
|
||||
@ -192,10 +200,18 @@ class Dashboard extends Component<Props, State> {
|
||||
this.update(msg);
|
||||
};
|
||||
server.onclose = () => {
|
||||
this.setState({server: null});
|
||||
setTimeout(this.reconnect, 3000);
|
||||
};
|
||||
};
|
||||
|
||||
// send sends a message to the server, which can be accessed only through this function for safety reasons.
|
||||
send = (msg: string) => {
|
||||
if (this.state.server != null) {
|
||||
this.state.server.send(msg);
|
||||
}
|
||||
};
|
||||
|
||||
// update updates the content corresponding to the incoming message.
|
||||
update = (msg: $Shape<Content>) => {
|
||||
this.setState(prevState => ({
|
||||
@ -226,6 +242,7 @@ class Dashboard extends Component<Props, State> {
|
||||
active={this.state.active}
|
||||
content={this.state.content}
|
||||
shouldUpdate={this.state.shouldUpdate}
|
||||
send={this.send}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
Reference in New Issue
Block a user