Skip to content

Commit 5df7479

Browse files
bwilkersonCommit Queue
authored andcommitted
Reorganize the status/diagnostic pages
I moved several classes out of `diagnostics.dart` into their own libraries under `pages`. I also moved one of the singling files into `pages`. Several other sibling pages were moved to `utilities`. In the process I needed to make a couple of methods public rather than private. There are no functional changes. I was going to split out the rest of the classes from `diagnostics.dart` and `pages.dart` but I haven't yet decided whether they should all go into a single directory or whether they should be in two directories. The classes in `pages.dart` appear to be classes appropriate for any web site generating code while those in `diagnostics.dart` are specific to this web site, but it isn't clear to me that the abstraction is helpful given that we only have one web site to build. Change-Id: Iff968bc3bfb654db24e896cb1ae0ced9bc6333fd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/432360 Reviewed-by: Samuel Rawlins <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent c006202 commit 5df7479

34 files changed

+2441
-2190
lines changed

pkg/analysis_server/lib/src/status/diagnostics.dart

Lines changed: 323 additions & 2188 deletions
Large diffs are not rendered by default.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:analysis_server/src/status/diagnostics.dart';
8+
import 'package:analysis_server/src/status/pages.dart';
9+
import 'package:analyzer/src/util/performance/operation_performance.dart';
10+
11+
class AnalysisDriverPage extends DiagnosticPageWithNav implements PostablePage {
12+
static const _resetFormId = 'reset-driver-timers';
13+
14+
AnalysisDriverPage(DiagnosticsSite site)
15+
: super(
16+
site,
17+
'analysis-driver',
18+
'Analysis driver',
19+
description:
20+
'Timing statistics collected by the analysis driver scheduler since the last reset.',
21+
indentInNav: true,
22+
);
23+
24+
@override
25+
Future<void> generateContent(Map<String, String> params) async {
26+
// Output the current values.
27+
var buffer = StringBuffer();
28+
server.analysisDriverScheduler.accumulatedPerformance.write(buffer: buffer);
29+
pre(() {
30+
buf.write('<code>');
31+
buf.write(escape('$buffer'));
32+
buf.writeln('</code>');
33+
});
34+
35+
// Add a button to reset the timers.
36+
buf.write('''
37+
<form action="$path?$_resetFormId=true" method="post">
38+
<input type="submit" class="btn btn-danger" value="Reset Timers" />
39+
</form>
40+
''');
41+
}
42+
43+
@override
44+
Future<String> handlePost(Map<String, String> params) async {
45+
if (params[_resetFormId]?.isNotEmpty ?? false) {
46+
server
47+
.analysisDriverScheduler
48+
.accumulatedPerformance = OperationPerformanceImpl('<scheduler>');
49+
}
50+
51+
return path;
52+
}
53+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'dart:io';
7+
8+
import 'package:analysis_server/src/status/diagnostics.dart';
9+
import 'package:analysis_server/src/utilities/stream_string_stink.dart';
10+
11+
class AnalysisPerformanceLogPage extends WebSocketLoggingPage {
12+
AnalysisPerformanceLogPage(DiagnosticsSite site)
13+
: super(
14+
site,
15+
'analysis-performance-log',
16+
'Analysis performance log',
17+
description: 'Real-time logging from the analysis performance log',
18+
);
19+
20+
@override
21+
Future<void> generateContent(Map<String, String> params) async {
22+
writeWebSocketLogPanel();
23+
}
24+
25+
@override
26+
Future<void> handleWebSocket(WebSocket socket) async {
27+
var logger = server.analysisPerformanceLogger;
28+
29+
// We were able to attach our temporary sink. Forward all data over the
30+
// WebSocket and wait for it to close (this is done by the user clicking
31+
// the Stop button or navigating away from the page).
32+
var controller = StreamController<String>();
33+
var sink = StreamStringSink(controller.sink);
34+
try {
35+
unawaited(socket.addStream(controller.stream));
36+
logger.sink.addSink(sink);
37+
38+
// Wait for the socket to be closed so we can remove the secondary sink.
39+
var completer = Completer<void>();
40+
socket.listen(
41+
null,
42+
onDone: completer.complete,
43+
onError: completer.complete,
44+
);
45+
await completer.future;
46+
} finally {
47+
logger.sink.removeSink(sink);
48+
}
49+
}
50+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:analysis_server/src/status/diagnostics.dart';
8+
import 'package:analysis_server/src/status/pages.dart';
9+
import 'package:analysis_server_plugin/src/correction/assist_performance.dart';
10+
import 'package:path/path.dart' as path;
11+
12+
class AssistsPage extends DiagnosticPageWithNav with PerformanceChartMixin {
13+
AssistsPage(DiagnosticsSite site)
14+
: super(
15+
site,
16+
'assists',
17+
'Assists',
18+
description: 'Latency and timing statistics for getting assists.',
19+
indentInNav: true,
20+
);
21+
22+
path.Context get pathContext => server.resourceProvider.pathContext;
23+
24+
List<GetAssistsPerformance> get performanceItems =>
25+
server.recentPerformance.getAssists.items.toList();
26+
27+
@override
28+
Future<void> generateContent(Map<String, String> params) async {
29+
var requests = performanceItems;
30+
31+
if (requests.isEmpty) {
32+
blankslate('No assist requests recorded.');
33+
return;
34+
}
35+
36+
var fastCount =
37+
requests.where((c) => c.elapsedInMilliseconds <= 100).length;
38+
p(
39+
'${requests.length} results; ${printPercentage(fastCount / requests.length)} within 100ms.',
40+
);
41+
42+
drawChart(requests);
43+
44+
// Emit the data as a table
45+
buf.writeln('<table>');
46+
buf.writeln(
47+
'<tr><th>Time</th><th align = "left" title="Time in correction producer `compute()` calls">Producer.compute()</th><th align = "left">Source</th><th>Snippet</th></tr>',
48+
);
49+
50+
for (var request in requests) {
51+
var shortName = pathContext.basename(request.path);
52+
var (:time, :details) = producerTimeAndDetails(request);
53+
buf.writeln(
54+
'<tr>'
55+
'<td class="pre right"><a href="/timing?id=${request.id}&kind=getAssists">'
56+
'${formatLatencyTiming(request.elapsedInMilliseconds, request.requestLatency)}'
57+
'</a></td>'
58+
'<td><abbr title="$details">${printMilliseconds(time)}</abbr></td>'
59+
'<td>${escape(shortName)}</td>'
60+
'<td><code>${escape(request.snippet)}</code></td>'
61+
'</tr>',
62+
);
63+
}
64+
buf.writeln('</table>');
65+
}
66+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:analysis_server/src/status/diagnostics.dart';
8+
import 'package:analysis_server/src/status/pages.dart';
9+
import 'package:analysis_server/src/status/utilities/ast_writer.dart';
10+
import 'package:analyzer/dart/analysis/results.dart';
11+
12+
class AstPage extends DiagnosticPageWithNav {
13+
String? _description;
14+
15+
AstPage(DiagnosticsSite site)
16+
: super(site, 'ast', 'AST', description: 'The AST for a file.');
17+
18+
@override
19+
String? get description => _description ?? super.description;
20+
21+
@override
22+
bool get showInNav => false;
23+
24+
@override
25+
Future<void> generateContent(Map<String, String> params) async {
26+
var filePath = params['file'];
27+
if (filePath == null) {
28+
p('No file path provided.');
29+
return;
30+
}
31+
var driver = server.getAnalysisDriver(filePath);
32+
if (driver == null) {
33+
p(
34+
'The file <code>${escape(filePath)}</code> is not being analyzed.',
35+
raw: true,
36+
);
37+
return;
38+
}
39+
var result = await driver.getResolvedUnit(filePath);
40+
if (result is ResolvedUnitResult) {
41+
var writer = AstWriter(buf);
42+
result.unit.accept(writer);
43+
} else {
44+
p(
45+
'An AST could not be produced for the file '
46+
'<code>${escape(filePath)}</code>.',
47+
raw: true,
48+
);
49+
}
50+
}
51+
52+
@override
53+
Future<void> generatePage(Map<String, String> params) async {
54+
try {
55+
_description = params['file'];
56+
await super.generatePage(params);
57+
} finally {
58+
_description = null;
59+
}
60+
}
61+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:analysis_server/src/status/diagnostics.dart';
8+
9+
class ClientPage extends DiagnosticPageWithNav {
10+
ClientPage(super.site, [super.id = 'client', super.title = 'Client'])
11+
: super(description: 'Information about the client.');
12+
13+
@override
14+
Future<void> generateContent(Map<String, String> params) async {
15+
h3('Client Diagnostic Information');
16+
prettyJson(server.clientDiagnosticInformation);
17+
}
18+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:analysis_server/src/services/completion/completion_performance.dart';
8+
import 'package:analysis_server/src/status/diagnostics.dart';
9+
import 'package:analysis_server/src/status/pages.dart';
10+
import 'package:path/path.dart' as path;
11+
12+
class CodeCompletionPage extends DiagnosticPageWithNav
13+
with PerformanceChartMixin {
14+
CodeCompletionPage(DiagnosticsSite site)
15+
: super(
16+
site,
17+
'code-completion',
18+
'Code Completion',
19+
description: 'Latency statistics for code completion.',
20+
indentInNav: true,
21+
);
22+
23+
path.Context get pathContext => server.resourceProvider.pathContext;
24+
25+
List<CompletionPerformance> get performanceItems =>
26+
server.recentPerformance.completion.items.toList();
27+
28+
@override
29+
Future<void> generateContent(Map<String, String> params) async {
30+
var completions = performanceItems;
31+
32+
if (completions.isEmpty) {
33+
blankslate('No completions recorded.');
34+
return;
35+
}
36+
37+
var fastCount =
38+
completions.where((c) => c.elapsedInMilliseconds <= 100).length;
39+
p(
40+
'${completions.length} results; ${printPercentage(fastCount / completions.length)} within 100ms.',
41+
);
42+
43+
drawChart(completions);
44+
45+
// emit the data as a table
46+
buf.writeln('<table>');
47+
buf.writeln(
48+
'<tr><th>Time</th><th>Computed Results</th><th>Transmitted Results</th><th>Source</th><th>Snippet</th></tr>',
49+
);
50+
for (var completion in completions) {
51+
var shortName = pathContext.basename(completion.path);
52+
buf.writeln(
53+
'<tr>'
54+
'<td class="pre right"><a href="/timing?id=${completion.id}&kind=completion">'
55+
'${formatLatencyTiming(completion.elapsedInMilliseconds, completion.requestLatency)}'
56+
'</a></td>'
57+
'<td class="right">${completion.computedSuggestionCountStr}</td>'
58+
'<td class="right">${completion.transmittedSuggestionCountStr}</td>'
59+
'<td>${escape(shortName)}</td>'
60+
'<td><code>${escape(completion.snippet)}</code></td>'
61+
'</tr>',
62+
);
63+
}
64+
buf.writeln('</table>');
65+
}
66+
}

0 commit comments

Comments
 (0)