| Index: pkg/analysis_server/tool/instrumentation/page/task_page.dart
|
| diff --git a/pkg/analysis_server/tool/instrumentation/page/task_page.dart b/pkg/analysis_server/tool/instrumentation/page/task_page.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5b34737844018e5d0738a6e4a81ae79d136fd4e1
|
| --- /dev/null
|
| +++ b/pkg/analysis_server/tool/instrumentation/page/task_page.dart
|
| @@ -0,0 +1,166 @@
|
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +import 'dart:math' as math;
|
| +
|
| +import '../log/log.dart';
|
| +import '../server.dart';
|
| +import 'page_writer.dart';
|
| +
|
| +/**
|
| + * A class used to write a human-readable version of the tasks executed within a
|
| + * single analysis step.
|
| + */
|
| +class TaskPage extends PageWriter {
|
| + /**
|
| + * The instrumentation log to be written.
|
| + */
|
| + final InstrumentationLog log;
|
| +
|
| + /**
|
| + * The index of the entry representing the start of an analysis session.
|
| + */
|
| + int analysisStart = 0;
|
| +
|
| + /**
|
| + * The index of the first task to be written.
|
| + */
|
| + int pageStart = 0;
|
| +
|
| + /**
|
| + * The number of tasks to be written, or `null` if all of the tasks should
|
| + * be written.
|
| + */
|
| + int pageLength = null;
|
| +
|
| + /**
|
| + * The number of digits in the event stamps that are the same for every task.
|
| + */
|
| + int prefixLength;
|
| +
|
| + /**
|
| + * Initialize a newly created page writer to write a single page worth of
|
| + * tasks.
|
| + */
|
| + TaskPage(this.log);
|
| +
|
| + @override
|
| + void writeBody(StringSink sink) {
|
| + writeMenu(sink);
|
| + writeTwoColumns(
|
| + sink, 'leftColumn', _writeLeftColumn, 'rightColumn', _writeRightColumn);
|
| + }
|
| +
|
| + @override
|
| + void writeScripts(StringSink sink) {
|
| + super.writeScripts(sink);
|
| + sink.writeln('function setDetails(detailsContent) {');
|
| + sink.writeln(' var element = document.getElementById("details");');
|
| + sink.writeln(' if (element != null) {');
|
| + sink.writeln(' element.innerHTML = detailsContent;');
|
| + sink.writeln(' }');
|
| + sink.writeln('}');
|
| + }
|
| +
|
| + /**
|
| + * Write the content of the style sheet (without the 'script' tag) for the
|
| + * page to the given [sink].
|
| + */
|
| + void writeStyleSheet(StringSink sink) {
|
| + super.writeStyleSheet(sink);
|
| + writeTwoColumnStyles(sink, 'leftColumn', 'rightColumn');
|
| + }
|
| +
|
| + /**
|
| + * Write the given log [entry] to the given [sink].
|
| + */
|
| + void _writeEntry(StringSink sink, TaskEntry entry) {
|
| + String clickHandler = 'setDetails(\'${escape(entry.details())}\')';
|
| + String timeStamp = entry.timeStamp.toString();
|
| + if (prefixLength > 0) {
|
| + timeStamp = timeStamp.substring(prefixLength);
|
| + }
|
| +
|
| + sink.writeln('<tr onclick="$clickHandler">');
|
| + sink.writeln('<td>');
|
| + sink.writeln(timeStamp);
|
| + sink.writeln('</td>');
|
| + sink.writeln('<td>');
|
| + sink.writeln(entry.taskName);
|
| + sink.writeln('</td>');
|
| + sink.writeln('<td style="white-space:nowrap;">');
|
| + sink.writeln(entry.target);
|
| + sink.writeln('</td>');
|
| + sink.writeln('</tr>');
|
| + }
|
| +
|
| + /**
|
| + * Write the entries in the instrumentation log to the given [sink].
|
| + */
|
| + void _writeLeftColumn(StringSink sink) {
|
| + List<TaskEntry> entries = log.taskEntriesFor(analysisStart);
|
| + prefixLength = computePrefixLength(entries);
|
| + int length = entries.length;
|
| + int pageEnd =
|
| + pageLength == null ? length : math.min(pageStart + pageLength, length);
|
| + //
|
| + // Write the header of the column.
|
| + //
|
| + sink.writeln('<div class="columnHeader">');
|
| + sink.writeln('<div style="float: left">');
|
| + sink.writeln('Tasks $pageStart - ${pageEnd - 1} of ${length - 1}');
|
| + sink.writeln('</div>');
|
| +
|
| + sink.writeln('<div style="float: right">');
|
| + if (pageStart == 0) {
|
| + sink.writeln('<button type="button" disabled><b><</b></button>');
|
| + } else {
|
| + sink.write('<button type="button">');
|
| + sink.write(
|
| + '<a href="${WebServer.taskPath}?analysisStart=$analysisStart&start=${pageStart - pageLength}">');
|
| + sink.write('<b><</b>');
|
| + sink.writeln('</a></button>');
|
| + }
|
| + // TODO(brianwilkerson) Add a text field for selecting the start index.
|
| + if (pageEnd == length) {
|
| + sink.writeln('<button type="button" disabled><b>></b></button>');
|
| + } else {
|
| + sink.write('<button type="button">');
|
| + sink.write(
|
| + '<a href="${WebServer.taskPath}?analysisStart=$analysisStart&start=${pageStart + pageLength}">');
|
| + sink.write('<b>></b>');
|
| + sink.writeln('</a></button>');
|
| + }
|
| + sink.writeln('</div>');
|
| + sink.writeln('</div>');
|
| + //
|
| + // Write the main body of the column.
|
| + //
|
| + sink.writeln('<table class="fullWidth">');
|
| + sink.writeln('<tr>');
|
| + sink.writeln('<th>Time</th>');
|
| + sink.writeln('<th>Task</th>');
|
| + sink.writeln('<th>Target</th>');
|
| + sink.writeln('</tr>');
|
| + for (int i = pageStart; i < pageEnd; i++) {
|
| + LogEntry entry = entries[i];
|
| + _writeEntry(sink, entry);
|
| + }
|
| + sink.writeln('</table>');
|
| + }
|
| +
|
| + /**
|
| + * Write a placeholder to the given [sink] where the details of a selected
|
| + * entry can be displayed.
|
| + */
|
| + void _writeRightColumn(StringSink sink) {
|
| + //
|
| + // Write the header of the column.
|
| + //
|
| + sink.writeln('<div class="columnHeader">');
|
| + sink.writeln('<p><b>Task Details</b></p>');
|
| + sink.writeln('</div>');
|
| + sink.writeln('<div id="details"></div>');
|
| + }
|
| +}
|
|
|