Skip to content

Commit a9835c1

Browse files
kurkomisikaralabe
authored andcommitted
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
1 parent 2eedbe7 commit a9835c1

File tree

28 files changed

+11214
-7981
lines changed

28 files changed

+11214
-7981
lines changed

cmd/geth/main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,12 @@ func init() {
199199

200200
app.Before = func(ctx *cli.Context) error {
201201
runtime.GOMAXPROCS(runtime.NumCPU())
202-
if err := debug.Setup(ctx); err != nil {
202+
203+
logdir := ""
204+
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
205+
logdir = (&node.Config{DataDir: utils.MakeDataDir(ctx)}).ResolvePath("logs")
206+
}
207+
if err := debug.Setup(ctx, logdir); err != nil {
203208
return err
204209
}
205210
// Cap the cache allowance and tune the garbage collector

cmd/swarm/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ pv(1) tool to get a progress bar:
432432
app.Flags = append(app.Flags, swarmmetrics.Flags...)
433433
app.Before = func(ctx *cli.Context) error {
434434
runtime.GOMAXPROCS(runtime.NumCPU())
435-
if err := debug.Setup(ctx); err != nil {
435+
if err := debug.Setup(ctx, ""); err != nil {
436436
return err
437437
}
438438
swarmmetrics.Setup(ctx)

cmd/utils/flags.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ var (
193193
}
194194
// Dashboard settings
195195
DashboardEnabledFlag = cli.BoolFlag{
196-
Name: "dashboard",
196+
Name: metrics.DashboardEnabledFlag,
197197
Usage: "Enable the dashboard",
198198
}
199199
DashboardAddrFlag = cli.StringFlag{
@@ -1185,7 +1185,7 @@ func RegisterEthService(stack *node.Node, cfg *eth.Config) {
11851185
// RegisterDashboardService adds a dashboard to the stack.
11861186
func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
11871187
stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
1188-
return dashboard.New(cfg, commit)
1188+
return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil
11891189
})
11901190
}
11911191

dashboard/assets.go

Lines changed: 9898 additions & 7754 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dashboard/assets/common.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,4 @@ export const styles = {
6868
light: {
6969
color: 'rgba(255, 255, 255, 0.54)',
7070
},
71-
}
71+
};

dashboard/assets/components/Body.jsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ const styles = {
3232
};
3333

3434
export type Props = {
35-
opened: boolean,
35+
opened: boolean,
3636
changeContent: string => void,
37-
active: string,
38-
content: Content,
39-
shouldUpdate: Object,
37+
active: string,
38+
content: Content,
39+
shouldUpdate: Object,
40+
send: string => void,
4041
};
4142

4243
// Body renders the body of the dashboard.
@@ -52,6 +53,7 @@ class Body extends Component<Props> {
5253
active={this.props.active}
5354
content={this.props.content}
5455
shouldUpdate={this.props.shouldUpdate}
56+
send={this.props.send}
5557
/>
5658
</div>
5759
);

dashboard/assets/components/CustomTooltip.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export type Props = {
8585
class CustomTooltip extends Component<Props> {
8686
render() {
8787
const {active, payload, tooltip} = this.props;
88-
if (!active || typeof tooltip !== 'function') {
88+
if (!active || typeof tooltip !== 'function' || !Array.isArray(payload) || payload.length < 1) {
8989
return null;
9090
}
9191
return tooltip(payload[0].value);

dashboard/assets/components/Dashboard.jsx

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import Header from './Header';
2424
import Body from './Body';
2525
import {MENU} from '../common';
2626
import type {Content} from '../types/content';
27+
import {inserter as logInserter} from './Logs';
2728

2829
// deepUpdate updates an object corresponding to the given update data, which has
2930
// 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
7576
...update.map(sample => mapper(sample)),
7677
].slice(-limit);
7778

78-
// defaultContent is the initial value of the state content.
79-
const defaultContent: Content = {
79+
// defaultContent returns the initial value of the state content. Needs to be a function in order to
80+
// instantiate the object again, because it is used by the state, and isn't automatically cleaned
81+
// when a new connection is established. The state is mutated during the update in order to avoid
82+
// the execution of unnecessary operations (e.g. copy of the log array).
83+
const defaultContent: () => Content = () => ({
8084
general: {
8185
version: null,
8286
commit: null,
@@ -95,10 +99,14 @@ const defaultContent: Content = {
9599
diskRead: [],
96100
diskWrite: [],
97101
},
98-
logs: {
99-
log: [],
102+
logs: {
103+
chunks: [],
104+
endTop: false,
105+
endBottom: true,
106+
topChanged: 0,
107+
bottomChanged: 0,
100108
},
101-
};
109+
});
102110

103111
// updaters contains the state updater functions for each path of the state.
104112
//
@@ -122,9 +130,7 @@ const updaters = {
122130
diskRead: appender(200),
123131
diskWrite: appender(200),
124132
},
125-
logs: {
126-
log: appender(200),
127-
},
133+
logs: logInserter(5),
128134
};
129135

130136
// styles contains the constant styles of the component.
@@ -151,10 +157,11 @@ export type Props = {
151157
};
152158

153159
type State = {
154-
active: string, // active menu
155-
sideBar: boolean, // true if the sidebar is opened
156-
content: Content, // the visualized data
157-
shouldUpdate: Object, // labels for the components, which need to re-render based on the incoming message
160+
active: string, // active menu
161+
sideBar: boolean, // true if the sidebar is opened
162+
content: Content, // the visualized data
163+
shouldUpdate: Object, // labels for the components, which need to re-render based on the incoming message
164+
server: ?WebSocket,
158165
};
159166

160167
// 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> {
165172
this.state = {
166173
active: MENU.get('home').id,
167174
sideBar: true,
168-
content: defaultContent,
175+
content: defaultContent(),
169176
shouldUpdate: {},
177+
server: null,
170178
};
171179
}
172180

@@ -181,7 +189,7 @@ class Dashboard extends Component<Props, State> {
181189
// PROD is defined by webpack.
182190
const server = new WebSocket(`${((window.location.protocol === 'https:') ? 'wss://' : 'ws://')}${PROD ? window.location.host : 'localhost:8080'}/api`);
183191
server.onopen = () => {
184-
this.setState({content: defaultContent, shouldUpdate: {}});
192+
this.setState({content: defaultContent(), shouldUpdate: {}, server});
185193
};
186194
server.onmessage = (event) => {
187195
const msg: $Shape<Content> = JSON.parse(event.data);
@@ -192,10 +200,18 @@ class Dashboard extends Component<Props, State> {
192200
this.update(msg);
193201
};
194202
server.onclose = () => {
203+
this.setState({server: null});
195204
setTimeout(this.reconnect, 3000);
196205
};
197206
};
198207

208+
// send sends a message to the server, which can be accessed only through this function for safety reasons.
209+
send = (msg: string) => {
210+
if (this.state.server != null) {
211+
this.state.server.send(msg);
212+
}
213+
};
214+
199215
// update updates the content corresponding to the incoming message.
200216
update = (msg: $Shape<Content>) => {
201217
this.setState(prevState => ({
@@ -226,6 +242,7 @@ class Dashboard extends Component<Props, State> {
226242
active={this.state.active}
227243
content={this.state.content}
228244
shouldUpdate={this.state.shouldUpdate}
245+
send={this.send}
229246
/>
230247
</div>
231248
);

0 commit comments

Comments
 (0)