From b294d2915d2b9063cdbc2b2fe4154954de3bcc84 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sat, 22 Sep 2018 13:11:56 -0700 Subject: [PATCH 1/2] misc logging improvements --- lib/logging/logging.dart | 49 +++++++++++++++++++++++++++------------- lib/memory/memory.dart | 7 ++---- lib/utils.dart | 7 +++++- test/test.md | 1 - test/utils_test.dart | 24 ++++++++++++++++++++ web/styles.css | 6 ++++- 6 files changed, 70 insertions(+), 24 deletions(-) create mode 100644 test/utils_test.dart diff --git a/lib/logging/logging.dart b/lib/logging/logging.dart index c418150f624..7d25dfe06fd 100644 --- a/lib/logging/logging.dart +++ b/lib/logging/logging.dart @@ -129,13 +129,21 @@ class LoggingScreen extends Screen { // Log GC events. service.onGCEvent.listen((Event e) { - final String summary = - '${e.json['reason']} collection, ${e.json['isolate']['name']}'; + final Map newSpace = e.json['new']; + final Map oldSpace = e.json['old']; + final Map isolateRef = e.json['isolate']; + + final int usedBytes = newSpace['used'] + oldSpace['used']; + final int capacityBytes = newSpace['capacity'] + oldSpace['capacity']; + + final String summary = '${isolateRef['name']} • ' + '${e.json['reason']} collection • ' + '${printMb(usedBytes)} MB used of ${printMb(capacityBytes)} MB'; final Map event = { 'reason': e.json['reason'], - 'new': e.json['new'], - 'old': e.json['old'], - 'isolate': e.json['isolate'], + 'new': newSpace, + 'old': oldSpace, + 'isolate': isolateRef, }; final String message = jsonEncode(event); _log(new LogData('gc', message, e.timestamp, summary: summary)); @@ -165,7 +173,14 @@ class LoggingScreen extends Screen { final bool isError = level != null && level >= Level.SEVERE.value ? true : false; - _log(new LogData(loggerName, message, e.timestamp, isError: isError)); + + _log(new LogData( + loggerName, + jsonEncode(logRecord), + e.timestamp, + isError: isError, + summary: message, + )); }); // Log Flutter frame events. @@ -174,18 +189,19 @@ class LoggingScreen extends Screen { final FrameInfo frame = FrameInfo.from(e.extensionData.data); final String frameInfo = - 'frame ${frame.number} ${frame.elapsedMs.toStringAsFixed(1).padLeft(4)}ms '; + '${frame.elapsedMs.toStringAsFixed(1).padLeft(4)}ms '; final String div = createFrameDivHtml(frame); + _log(new LogData('${e.extensionKind.toLowerCase()}', + jsonEncode(e.extensionData.data), e.timestamp, + summaryHtml: '$frameInfo$div')); + } else { _log(new LogData( '${e.extensionKind.toLowerCase()}', - '', + jsonEncode(e.json), e.timestamp, - extraHtml: '$frameInfo$div', + summary: e.json.toString(), )); - } else { - _log(new LogData('${e.extensionKind.toLowerCase()}', e.json.toString(), - e.timestamp)); } }); } @@ -241,16 +257,16 @@ class LogData { final String message; final int timestamp; final bool isError; - final String extraHtml; final String summary; + final String summaryHtml; LogData( this.kind, this.message, this.timestamp, { this.isError = false, - this.extraHtml, this.summary, + this.summaryHtml, }); } @@ -314,8 +330,8 @@ class LogMessageColumn extends Column { String render(dynamic value) { final LogData log = value; - if (log.extraHtml != null) { - return '${log.summary ?? log.message} ${log.extraHtml}'; + if (log.summaryHtml != null) { + return log.summaryHtml; } else { // TODO(devoncarew): escape html return log.summary ?? log.message; @@ -335,6 +351,7 @@ String getCssClassForEventKind(LogData item) { } else if (item.kind == 'gc') { cssClass = 'gc'; } + return cssClass; } diff --git a/lib/memory/memory.dart b/lib/memory/memory.dart index e8fa314150a..226d319193f 100644 --- a/lib/memory/memory.dart +++ b/lib/memory/memory.dart @@ -313,12 +313,12 @@ class MemoryChart extends LineChart { } // display the process usage - final String rss = '${_printMb(data.processRss ?? 0, 0)} MB RSS'; + final String rss = '${printMb(data.processRss ?? 0, 0)} MB RSS'; processLabel.text = rss; // display the dart heap usage final String used = - '${_printMb(data.currentHeap, 1)} of ${_printMb(data.heapMax, 1)} MB'; + '${printMb(data.currentHeap, 1)} of ${printMb(data.heapMax, 1)} MB'; heapLabel.text = used; // re-render the svg @@ -489,9 +489,6 @@ class HeapSample { HeapSample(this.bytes, this.time, this.isGC); } -String _printMb(num bytes, int fractionDigits) => - (bytes / (1024 * 1024)).toStringAsFixed(fractionDigits); - // { // type: ClassHeapStats, // class: {type: @Class, fixedId: true, id: classes/5, name: Class}, diff --git a/lib/utils.dart b/lib/utils.dart index eda20dfc65e..1e837c9d0fa 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -51,6 +51,10 @@ String percent(double d) => '${(d * 100).toStringAsFixed(1)}%'; String percent2(double d) => '${(d * 100).toStringAsFixed(2)}%'; +String printMb(num bytes, [int fractionDigits = 1]) { + return (bytes / (1024 * 1024)).toStringAsFixed(fractionDigits); +} + String isolateName(IsolateRef ref) { // analysis_server.dart.snapshot$main String name = ref.name; @@ -100,7 +104,8 @@ Directory getDartPrefsDirectory() { /// Return the user's home directory. String getUserHomeDir() { - final String envKey = Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME'; + final String envKey = + Platform.operatingSystem == 'windows' ? 'APPDATA' : 'HOME'; final String value = Platform.environment[envKey]; return value == null ? '.' : value; } diff --git a/test/test.md b/test/test.md index 8149dc1be43..0129d5fd98b 100644 --- a/test/test.md +++ b/test/test.md @@ -1,4 +1,3 @@ - ## plan for integration tests Integration tests are expected to be heavyweight and test broad areas of a diff --git a/test/utils_test.dart b/test/utils_test.dart new file mode 100644 index 00000000000..fc02da9560b --- /dev/null +++ b/test/utils_test.dart @@ -0,0 +1,24 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:devtools/utils.dart'; +import 'package:test/test.dart'; + +void main() { + group('utils', () { + test('printMb', () { + const int MB = 1024 * 1024; + + expect(printMb(10 * MB, 0), '10'); + expect(printMb(10 * MB), '10.0'); + expect(printMb(10 * MB, 1), '10.0'); + expect(printMb(10 * MB, 2), '10.00'); + + expect(printMb(1000 * MB, 0), '1000'); + expect(printMb(1000 * MB), '1000.0'); + expect(printMb(1000 * MB, 1), '1000.0'); + expect(printMb(1000 * MB, 2), '1000.00'); + }); + }); +} diff --git a/web/styles.css b/web/styles.css index aeb7db94d89..902280f82cd 100644 --- a/web/styles.css +++ b/web/styles.css @@ -203,6 +203,10 @@ table tr.selected { border-radius: 1px; } +tr.selected .frame-bar { + background: #fff; +} + .frame-bar.over-budget { background: #f97c7c; } @@ -469,7 +473,7 @@ div.tabnav { .log-details { - height: 120px; + height: 126px; overflow-y: scroll; overflow-wrap: break-word; } From f8d4d360470feed9b2624142575fac48bfb1096c Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sun, 23 Sep 2018 12:40:54 -0700 Subject: [PATCH 2/2] escape html in stdout messages --- lib/logging/logging.dart | 3 +-- lib/tables.dart | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/logging/logging.dart b/lib/logging/logging.dart index 7d25dfe06fd..17e1ecdbce0 100644 --- a/lib/logging/logging.dart +++ b/lib/logging/logging.dart @@ -333,8 +333,7 @@ class LogMessageColumn extends Column { if (log.summaryHtml != null) { return log.summaryHtml; } else { - // TODO(devoncarew): escape html - return log.summary ?? log.message; + return escape(log.summary ?? log.message); } } } diff --git a/lib/tables.dart b/lib/tables.dart index f5296462594..ab6aced7f85 100644 --- a/lib/tables.dart +++ b/lib/tables.dart @@ -327,7 +327,7 @@ class Table extends Object with SetStateMixin { } if (column.usesHtml) { - tableCell..setInnerHtml(column.render(column.getValue(row))); + tableCell.setInnerHtml(column.render(column.getValue(row))); } else { tableCell.text = column.render(column.getValue(row)); }