Skip to content

Commit 4ea9b62

Browse files
kurkomisifjl
authored andcommitted
dashboard: send current block to the dashboard client (#19762)
This adds all dashboard changes from the last couple months. We're about to remove the dashboard, but decided that we should get all the recent work in first in case anyone wants to pick up this project later on. * cmd, dashboard, eth, p2p: send peer info to the dashboard * dashboard: update npm packages, improve UI, rebase * dashboard, p2p: remove println, change doc * cmd, dashboard, eth, p2p: cleanup after review * dashboard: send current block to the dashboard client
1 parent 6f1a600 commit 4ea9b62

File tree

20 files changed

+15775
-14732
lines changed

20 files changed

+15775
-14732
lines changed

cmd/geth/config.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,6 @@ func makeFullNode(ctx *cli.Context) *node.Node {
156156
}
157157
utils.RegisterEthService(stack, &cfg.Eth)
158158

159-
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
160-
utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
161-
}
162159
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
163160
shhEnabled := enableWhisper(ctx)
164161
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
@@ -182,6 +179,12 @@ func makeFullNode(ctx *cli.Context) *node.Node {
182179
if cfg.Ethstats.URL != "" {
183180
utils.RegisterEthStatsService(stack, cfg.Ethstats.URL)
184181
}
182+
183+
// Add dashboard daemon if requested. This should be the last registered service
184+
// in order to be able to collect information about the other services.
185+
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
186+
utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
187+
}
185188
return stack
186189
}
187190

cmd/utils/flags.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,9 +1561,18 @@ func RegisterEthService(stack *node.Node, cfg *eth.Config) {
15611561

15621562
// RegisterDashboardService adds a dashboard to the stack.
15631563
func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
1564-
stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
1565-
return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil
1564+
err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
1565+
var (
1566+
ethServ *eth.Ethereum
1567+
lesServ *les.LightEthereum
1568+
)
1569+
_ = ctx.Service(&ethServ)
1570+
_ = ctx.Service(&lesServ)
1571+
return dashboard.New(cfg, ethServ, lesServ, commit, ctx.ResolvePath("logs")), nil
15661572
})
1573+
if err != nil {
1574+
Fatalf("Failed to register the dashboard service: %v", err)
1575+
}
15671576
}
15681577

15691578
// RegisterShhService configures Whisper and adds it to the given node.

dashboard/assets.go

Lines changed: 13981 additions & 13595 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// @flow
2+
3+
// Copyright 2019 The go-ethereum Authors
4+
// This file is part of the go-ethereum library.
5+
//
6+
// The go-ethereum library is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Lesser General Public License as published by
8+
// the Free Software Foundation, either version 3 of the License, or
9+
// (at your option) any later version.
10+
//
11+
// The go-ethereum library is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Lesser General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Lesser General Public License
17+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
18+
19+
import React, {Component} from 'react';
20+
import type {Chain as ChainType} from '../types/content';
21+
22+
export const inserter = () => (update: ChainType, prev: ChainType) => {
23+
if (!update.currentBlock) {
24+
return;
25+
}
26+
if (!prev.currentBlock) {
27+
prev.currentBlock = {};
28+
}
29+
prev.currentBlock.number = update.currentBlock.number;
30+
prev.currentBlock.timestamp = update.currentBlock.timestamp;
31+
return prev;
32+
};
33+
34+
// styles contains the constant styles of the component.
35+
const styles = {};
36+
37+
// themeStyles returns the styles generated from the theme for the component.
38+
const themeStyles = theme => ({});
39+
40+
export type Props = {
41+
content: Content,
42+
};
43+
44+
type State = {};
45+
46+
// Logs renders the log page.
47+
class Chain extends Component<Props, State> {
48+
render() {
49+
return <></>;
50+
}
51+
}
52+
53+
export default Chain;

dashboard/assets/components/Dashboard.jsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Header from 'Header';
2525
import Body from 'Body';
2626
import {inserter as logInserter, SAME} from 'Logs';
2727
import {inserter as peerInserter} from 'Network';
28+
import {inserter as chainInserter} from 'Chain';
2829
import {MENU} from '../common';
2930
import type {Content} from '../types/content';
3031

@@ -83,17 +84,24 @@ const appender = <T>(limit: number, mapper = replacer) => (update: Array<T>, pre
8384
// the execution of unnecessary operations (e.g. copy of the log array).
8485
const defaultContent: () => Content = () => ({
8586
general: {
86-
version: null,
8787
commit: null,
88+
version: null,
89+
genesis: '',
90+
},
91+
home: {},
92+
chain: {
93+
currentBlock: {
94+
number: 0,
95+
timestamp: 0,
96+
},
8897
},
89-
home: {},
90-
chain: {},
9198
txpool: {},
9299
network: {
93100
peers: {
94101
bundles: {},
95102
},
96-
diff: [],
103+
diff: [],
104+
activePeerCount: 0,
97105
},
98106
system: {
99107
activeMemory: [],
@@ -121,9 +129,10 @@ const updaters = {
121129
general: {
122130
version: replacer,
123131
commit: replacer,
132+
genesis: replacer,
124133
},
125134
home: null,
126-
chain: null,
135+
chain: chainInserter(),
127136
txpool: null,
128137
network: peerInserter(200),
129138
system: {
@@ -241,6 +250,7 @@ class Dashboard extends Component<Props, State> {
241250
<div className={this.props.classes.dashboard} style={styles.dashboard}>
242251
<Header
243252
switchSideBar={this.switchSideBar}
253+
content={this.state.content}
244254
/>
245255
<Body
246256
opened={this.state.sideBar}

dashboard/assets/components/Footer.jsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ import ChartRow from 'ChartRow';
3232
import CustomTooltip, {bytePlotter, bytePerSecPlotter, percentPlotter, multiplier} from 'CustomTooltip';
3333
import {chartStrokeWidth, styles as commonStyles} from '../common';
3434
import type {General, System} from '../types/content';
35+
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
36+
import {faNetworkWired} from "@fortawesome/free-solid-svg-icons";
37+
import Toolbar from "@material-ui/core/Toolbar";
3538

3639
const FOOTER_SYNC_ID = 'footerSyncId';
3740

@@ -154,6 +157,23 @@ class Footer extends Component<Props, State> {
154157

155158
render() {
156159
const {general, system} = this.props;
160+
let network = '';
161+
switch (general.genesis) {
162+
case '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3':
163+
network = 'main';
164+
break;
165+
case '0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d':
166+
network = 'ropsten';
167+
break;
168+
case '0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177':
169+
network = 'rinkeby';
170+
break;
171+
case '0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a':
172+
network = 'görli';
173+
break;
174+
default:
175+
network = `unknown (${general.genesis.substring(0, 8)})`;
176+
}
157177

158178
return (
159179
<Grid container className={this.props.classes.footer} direction='row' alignItems='center' style={styles.footer}>
@@ -202,6 +222,9 @@ class Footer extends Component<Props, State> {
202222
</a>
203223
</Typography>
204224
)}
225+
<Typography style={styles.headerText}>
226+
<span style={commonStyles.light}>Network</span> {network}
227+
</Typography>
205228
</Grid>
206229
</Grid>
207230
);

dashboard/assets/components/Header.jsx

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,25 @@ import AppBar from '@material-ui/core/AppBar';
2323
import Toolbar from '@material-ui/core/Toolbar';
2424
import IconButton from '@material-ui/core/IconButton';
2525
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
26-
import {faBars} from '@fortawesome/free-solid-svg-icons';
26+
import {faBars, faSortAmountUp, faClock, faUsers, faSync} from '@fortawesome/free-solid-svg-icons';
2727
import Typography from '@material-ui/core/Typography';
28+
import type {Content} from '../types/content';
29+
30+
31+
const magnitude = [31536000, 604800, 86400, 3600, 60, 1];
32+
const label = ['y', 'w', 'd', 'h', 'm', 's'];
2833

2934
// styles contains the constant styles of the component.
3035
const styles = {
3136
header: {
3237
height: '8%',
3338
},
39+
headerText: {
40+
marginRight: 15,
41+
},
3442
toolbar: {
35-
height: '100%',
43+
height: '100%',
44+
minHeight: 'unset',
3645
},
3746
};
3847

@@ -50,16 +59,52 @@ const themeStyles = (theme: Object) => ({
5059
title: {
5160
paddingLeft: theme.spacing.unit,
5261
fontSize: 3 * theme.spacing.unit,
62+
flex: 1,
5363
},
5464
});
5565

5666
export type Props = {
57-
classes: Object, // injected by withStyles()
67+
classes: Object, // injected by withStyles()
5868
switchSideBar: () => void,
69+
content: Content,
70+
networkID: number,
5971
};
6072

73+
type State = {
74+
since: string,
75+
}
6176
// Header renders the header of the dashboard.
62-
class Header extends Component<Props> {
77+
class Header extends Component<Props, State> {
78+
constructor(props) {
79+
super(props);
80+
this.state = {since: ''};
81+
}
82+
83+
componentDidMount() {
84+
this.interval = setInterval(() => this.setState(() => {
85+
// time (seconds) since last block.
86+
let timeDiff = Math.floor((Date.now() - this.props.content.chain.currentBlock.timestamp * 1000) / 1000);
87+
let since = '';
88+
let i = 0;
89+
for (; i < magnitude.length && timeDiff < magnitude[i]; i++);
90+
for (let j = 2; i < magnitude.length && j > 0; j--, i++) {
91+
const t = Math.floor(timeDiff / magnitude[i]);
92+
if (t > 0) {
93+
since += `${t}${label[i]} `;
94+
timeDiff %= magnitude[i];
95+
}
96+
}
97+
if (since === '') {
98+
since = 'now';
99+
}
100+
this.setState({since: since});
101+
}), 1000);
102+
}
103+
104+
componentWillUnmount() {
105+
clearInterval(this.interval);
106+
}
107+
63108
render() {
64109
const {classes} = this.props;
65110

@@ -72,6 +117,15 @@ class Header extends Component<Props> {
72117
<Typography type='title' color='inherit' noWrap className={classes.title}>
73118
Go Ethereum Dashboard
74119
</Typography>
120+
<Typography style={styles.headerText}>
121+
<FontAwesomeIcon icon={faSortAmountUp} /> {this.props.content.chain.currentBlock.number}
122+
</Typography>
123+
<Typography style={styles.headerText}>
124+
<FontAwesomeIcon icon={faClock} /> {this.state.since}
125+
</Typography>
126+
<Typography style={styles.headerText}>
127+
<FontAwesomeIcon icon={faUsers} /> {this.props.content.network.activePeerCount}
128+
</Typography>
75129
</Toolbar>
76130
</AppBar>
77131
);

dashboard/assets/components/Main.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import React, {Component} from 'react';
2020

2121
import withStyles from '@material-ui/core/styles/withStyles';
2222

23+
import Chain from 'Chain';
2324
import Network from 'Network';
2425
import Logs from 'Logs';
2526
import Footer from 'Footer';
@@ -95,7 +96,9 @@ class Main extends Component<Props, State> {
9596
children = <div>Work in progress.</div>;
9697
break;
9798
case MENU.get('chain').id:
98-
children = <div>Work in progress.</div>;
99+
children = <Chain
100+
content={this.props.content.chain}
101+
/>;
99102
break;
100103
case MENU.get('txpool').id:
101104
children = <div>Work in progress.</div>;

0 commit comments

Comments
 (0)