Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ profile.cov

# IdeaIDE
.idea

# dashboard
/dashboard/assets/node_modules
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix all your files so they have a newline at the end.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also skip the bundle.js, since it's an intermediate build step between source jsx and the final assets.go

/dashboard/assets/stats.json
/dashboard/assets/public/bundle.js
21 changes: 14 additions & 7 deletions cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (

"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/contracts/release"
"github.com/ethereum/go-ethereum/dashboard"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
Expand Down Expand Up @@ -76,10 +77,11 @@ type ethstatsConfig struct {
}

type gethConfig struct {
Eth eth.Config
Shh whisper.Config
Node node.Config
Ethstats ethstatsConfig
Eth eth.Config
Shh whisper.Config
Node node.Config
Ethstats ethstatsConfig
Dashboard dashboard.Config
}

func loadConfig(file string, cfg *gethConfig) error {
Expand Down Expand Up @@ -110,9 +112,10 @@ func defaultNodeConfig() node.Config {
func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
// Load defaults.
cfg := gethConfig{
Eth: eth.DefaultConfig,
Shh: whisper.DefaultConfig,
Node: defaultNodeConfig(),
Eth: eth.DefaultConfig,
Shh: whisper.DefaultConfig,
Node: defaultNodeConfig(),
Dashboard: dashboard.DefaultConfig,
}

// Load config file.
Expand All @@ -134,6 +137,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
}

utils.SetShhConfig(ctx, stack, &cfg.Shh)
utils.SetDashboardConfig(ctx, &cfg.Dashboard)

return stack, cfg
}
Expand All @@ -153,6 +157,9 @@ func makeFullNode(ctx *cli.Context) *node.Node {

utils.RegisterEthService(stack, &cfg.Eth)

if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
utils.RegisterDashboardService(stack, &cfg.Dashboard)
}
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
shhEnabled := enableWhisper(ctx)
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
Expand Down
5 changes: 5 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ var (
utils.DataDirFlag,
utils.KeyStoreDirFlag,
utils.NoUSBFlag,
utils.DashboardEnabledFlag,
utils.DashboardAddrFlag,
utils.DashboardPortFlag,
utils.DashboardRefreshFlag,
utils.DashboardAssetsFlag,
utils.EthashCacheDirFlag,
utils.EthashCachesInMemoryFlag,
utils.EthashCachesOnDiskFlag,
Expand Down
14 changes: 14 additions & 0 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/internal/debug"
"gopkg.in/urfave/cli.v1"
"strings"
)

// AppHelpTemplate is the test template for the default, global app help topic.
Expand Down Expand Up @@ -97,6 +98,16 @@ var AppHelpFlagGroups = []flagGroup{
utils.EthashDatasetsOnDiskFlag,
},
},
//{
// Name: "DASHBOARD",
// Flags: []cli.Flag{
// utils.DashboardEnabledFlag,
// utils.DashboardAddrFlag,
// utils.DashboardPortFlag,
// utils.DashboardRefreshFlag,
// utils.DashboardAssetsFlag,
// },
//},
{
Name: "TRANSACTION POOL",
Flags: []cli.Flag{
Expand Down Expand Up @@ -268,6 +279,9 @@ func init() {
uncategorized := []cli.Flag{}
for _, flag := range data.(*cli.App).Flags {
if _, ok := categorized[flag.String()]; !ok {
if strings.HasPrefix(flag.GetName(), "dashboard") {
continue
}
uncategorized = append(uncategorized, flag)
}
}
Expand Down
41 changes: 41 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/dashboard"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice"
Expand Down Expand Up @@ -183,6 +184,31 @@ var (
Name: "lightkdf",
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
}
// Dashboard settings
DashboardEnabledFlag = cli.BoolFlag{
Name: "dashboard",
Usage: "Enable the dashboard",
}
DashboardAddrFlag = cli.StringFlag{
Name: "dashboard.addr",
Usage: "Dashboard listening interface",
Value: dashboard.DefaultConfig.Host,
}
DashboardPortFlag = cli.IntFlag{
Name: "dashboard.host",
Usage: "Dashboard listening port",
Value: dashboard.DefaultConfig.Port,
}
DashboardRefreshFlag = cli.DurationFlag{
Name: "dashboard.refresh",
Usage: "Dashboard metrics collection refresh rate",
Value: dashboard.DefaultConfig.Refresh,
}
DashboardAssetsFlag = cli.StringFlag{
Name: "dashboard.assets",
Usage: "Developer flag to serve the dashboard from the local file system",
Value: dashboard.DefaultConfig.Assets,
}
// Ethash settings
EthashCacheDirFlag = DirectoryFlag{
Name: "ethash.cachedir",
Expand Down Expand Up @@ -1019,6 +1045,14 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
}
}

// SetDashboardConfig applies dashboard related command line flags to the config.
func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
cfg.Assets = ctx.GlobalString(DashboardAssetsFlag.Name)
}

// RegisterEthService adds an Ethereum client to the stack.
func RegisterEthService(stack *node.Node, cfg *eth.Config) {
var err error
Expand All @@ -1041,6 +1075,13 @@ func RegisterEthService(stack *node.Node, cfg *eth.Config) {
}
}

// RegisterDashboardService adds a dashboard to the stack.
func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config) {
stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
return dashboard.New(cfg)
})
}

// RegisterShhService configures Whisper and adds it to the given node.
func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
Expand Down
46 changes: 46 additions & 0 deletions dashboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Go Ethereum Dashboard

The dashboard is a data visualizer integrated into geth, intended to collect and visualize useful information of an Ethereum node. It consists of two parts:

* The client visualizes the collected data.
* The server collects the data, and updates the clients.

The client's UI uses [React][React] with JSX syntax, which is validated by the [ESLint][ESLint] linter mostly according to the [Airbnb React/JSX Style Guide][Airbnb]. The style is defined in the `.eslintrc` configuration file. The resources are bundled into a single `bundle.js` file using [Webpack][Webpack], which relies on the `webpack.config.js`. The bundled file is referenced from `dashboard.html` and takes part in the `assets.go` too. The necessary dependencies for the module bundler are gathered by [Node.js][Node.js].

### Development and bundling

As the dashboard depends on certain NPM packages (which are not included in the go-ethereum repo), these need to be installed first:

```
$ (cd dashboard/assets && npm install)
```

Normally the dashboard assets are bundled into Geth via `go-bindata` to avoid external dependencies. Rebuilding Geth after each UI modification however is not feasible from a developer perspective. Instead, we can run `webpack` in watch mode to automatically rebundle the UI, and ask `geth` to use external assets to not rely on compiled resources:

```
$ (cd dashboard/assets && ./node_modules/.bin/webpack --watch)
$ geth --dashboard --dashboard.assets=dashboard/assets/public --vmodule=dashboard=5
```

To bundle up the final UI into Geth, run `webpack` and `go generate`:

```
$ (cd dashboard/assets && ./node_modules/.bin/webpack)
$ go generate ./dashboard
```

### Have fun

[Webpack][Webpack] offers handy tools for visualizing the bundle's dependency tree and space usage.

* Generate the bundle's profile running `webpack --profile --json > stats.json`
* For the _dependency tree_ go to [Webpack Analyze][WA], and import `stats.json`
* For the _space usage_ go to [Webpack Visualizer][WV], and import `stats.json`

[React]: https://reactjs.org/
[ESLint]: https://eslint.org/
[Airbnb]: https://github.com/airbnb/javascript/tree/master/react
[Webpack]: https://webpack.github.io/
[WA]: http://webpack.github.io/analyse/
[WV]: http://chrisbateman.github.io/webpack-visualizer/
[Node.js]: https://nodejs.org/en/
260 changes: 260 additions & 0 deletions dashboard/assets.go

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions dashboard/assets/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

// React syntax style mostly according to https://github.com/airbnb/javascript/tree/master/react
{
"plugins": [
"react"
],
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
"jsx": true,
"modules": true
}
},
"rules": {
"react/prefer-es6-class": 2,
"react/prefer-stateless-function": 2,
"react/jsx-pascal-case": 2,
"react/jsx-closing-bracket-location": [1, {"selfClosing": "tag-aligned", "nonEmpty": "tag-aligned"}],
"react/jsx-closing-tag-location": 1,
"jsx-quotes": ["error", "prefer-double"],
"no-multi-spaces": "error",
"react/jsx-tag-spacing": 2,
"react/jsx-curly-spacing": [2, {"when": "never", "children": true}],
"react/jsx-boolean-value": 2,
"react/no-string-refs": 2,
"react/jsx-wrap-multilines": 2,
"react/self-closing-comp": 2,
"react/jsx-no-bind": 2,
"react/require-render-return": 2,
"react/no-is-mounted": 2,
"key-spacing": ["error", {"align": {
"beforeColon": false,
"afterColon": true,
"on": "value"
}}]
}
}
52 changes: 52 additions & 0 deletions dashboard/assets/components/Common.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

// isNullOrUndefined returns true if the given variable is null or undefined.
export const isNullOrUndefined = variable => variable === null || typeof variable === 'undefined';

export const LIMIT = {
memory: 200, // Maximum number of memory data samples.
traffic: 200, // Maximum number of traffic data samples.
log: 200, // Maximum number of logs.
};
// The sidebar menu and the main content are rendered based on these elements.
export const TAGS = (() => {
const T = {
home: { title: "Home", },
chain: { title: "Chain", },
transactions: { title: "Transactions", },
network: { title: "Network", },
system: { title: "System", },
logs: { title: "Logs", },
};
// Using the key is circumstantial in some cases, so it is better to insert it also as a value.
// This way the mistyping is prevented.
for(let key in T) {
T[key]['id'] = key;
}
return T;
})();

export const DATA_KEYS = (() => {
const DK = {};
["memory", "traffic", "logs"].map(key => {
DK[key] = key;
});
return DK;
})();

// Temporary - taken from Material-UI
export const DRAWER_WIDTH = 240;
Loading