Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(447)

Side by Side Diff: runtime/observatory/lib/src/elements/logging.dart

Issue 2299893003: Converted Observatory logging-page element (Closed)
Patch Set: Updated observatory_sources.gypi Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library logging_page; 5 library logging_page;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'observatory_element.dart';
10 import 'package:logging/logging.dart'; 9 import 'package:logging/logging.dart';
11 import 'package:observatory/service.dart'; 10 import 'package:observatory/models.dart' as M;
12 import 'package:observatory/app.dart'; 11 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
13 import 'package:observatory/elements.dart'; 12 import 'package:observatory/src/elements/helpers/tag.dart';
14 import 'package:observatory/utils.dart'; 13 import 'package:observatory/src/elements/logging_list.dart';
15 import 'package:polymer/polymer.dart'; 14 import 'package:observatory/src/elements/nav/bar.dart';
15 import 'package:observatory/src/elements/nav/class_menu.dart';
16 import 'package:observatory/src/elements/nav/isolate_menu.dart';
17 import 'package:observatory/src/elements/nav/menu.dart';
18 import 'package:observatory/src/elements/nav/notify.dart';
19 import 'package:observatory/src/elements/nav/refresh.dart';
20 import 'package:observatory/src/elements/nav/top_menu.dart';
21 import 'package:observatory/src/elements/nav/vm_menu.dart';
22 import 'package:observatory/src/elements/view_footer.dart';
16 23
17 @CustomTag('logging-page') 24 class LoggingPageElement extends HtmlElement implements Renderable {
18 class LoggingPageElement extends ObservatoryElement { 25 static const tag = const Tag<LoggingPageElement>('logging-page',
19 static const _kPageSelector = '#page'; 26 dependencies: const [
20 static const _kLogSelector = '#log'; 27 LoggingListElement.tag,
21 static const _kSeverityLevelSelector = '#severityLevelSelector'; 28 NavBarElement.tag,
29 NavClassMenuElement.tag,
30 NavTopMenuElement.tag,
31 NavVMMenuElement.tag,
32 NavIsolateMenuElement.tag,
33 NavMenuElement.tag,
34 NavRefreshElement.tag,
35 NavNotifyElement.tag,
36 ViewFooterElement.tag
37 ]);
38
39 RenderingScheduler<LoggingPageElement> _r;
40
41 Stream<RenderedEvent<LoggingPageElement>> get onRendered => _r.onRendered;
42
43 M.VM _vm;
44 M.IsolateRef _isolate;
45 M.EventRepository _events;
46 M.NotificationRepository _notifications;
47 Level _level = Level.ALL;
48
49
50 M.VMRef get vm => _vm;
51 M.IsolateRef get isolate => _isolate;
52 M.NotificationRepository get notifications => _notifications;
53
54 factory LoggingPageElement(M.VM vm, M.IsolateRef isolate,
55 M.EventRepository events,
56 M.NotificationRepository notifications,
57 {RenderingQueue queue}) {
58 assert(vm != null);
59 assert(isolate != null);
60 assert(events != null);
61 assert(notifications != null);
62 LoggingPageElement e = document.createElement(tag.name);
63 e._r = new RenderingScheduler(e, queue: queue);
64 e._vm = vm;
65 e._isolate = isolate;
66 e._events = events;
67 e._notifications = notifications;
68 return e;
69 }
22 70
23 LoggingPageElement.created() : super.created(); 71 LoggingPageElement.created() : super.created();
24 72
25 domReady() { 73 @override
26 super.domReady(); 74 attached() {
27 _insertLevels(); 75 super.attached();
76 _r.enable();
28 } 77 }
29 78
30 attached() { 79 @override
31 super.attached(); 80 detached() {
32 _sub(); 81 super.detached();
33 _resizeSubscription = window.onResize.listen((_) => _updatePageHeight()); 82 _r.disable(notify: true);
34 _updatePageHeight(); 83 children = [];
35 // Turn on the periodic poll timer for this page.
36 pollPeriod = const Duration(milliseconds:100);
37 } 84 }
38 85
39 detached() { 86 LoggingListElement _logs;
40 super.detached(); 87
41 if (_resizeSubscription != null) { 88 void render() {
42 _resizeSubscription.cancel(); 89 _logs = _logs ?? new LoggingListElement(_isolate, _events);
43 _resizeSubscription = null; 90 _logs.level = _level;
44 } 91 children = [
45 _unsub(); 92 new NavBarElement(queue: _r.queue)
93 ..children = [
94 new NavTopMenuElement(queue: _r.queue),
95 new NavVMMenuElement(_vm, _events, queue: _r.queue),
96 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
97 new NavMenuElement('logging', last: true, queue: _r.queue),
98 new NavRefreshElement(label: 'clear', queue: _r.queue)
99 ..onRefresh.listen((e) async {
100 e.element.disabled = true;
101 _logs = null;
102 _r.dirty();
103 }),
104 new NavNotifyElement(_notifications, queue: _r.queue)
105 ],
106 new DivElement()..classes = ['content-centered-big']
107 ..children = [
108 new HeadingElement.h2()..text = 'Logging',
109 new SpanElement()
110 ..text = 'Show messages with severity ',
111 _createLevelSelector(),
112 new HRElement(),
113 _logs
114 ]
115 ];
46 } 116 }
47 117
48 void onPoll() { 118 Element _createLevelSelector() {
49 _flushPendingLogs(); 119 var s = new SelectElement()
120 ..value = _level.name
121 ..children = Level.LEVELS.map((level) {
122 return new OptionElement(value : level.name,
123 selected: _level == level)
124 ..text = level.name;
125 }).toList(growable: false);
126 s.onChange.listen((_) {
127 _level = Level.LEVELS[s.selectedIndex];
128 _r.dirty();
129 });
130 return s;
50 } 131 }
51
52 _updatePageHeight() {
53 HtmlElement e = shadowRoot.querySelector(_kPageSelector);
54 final totalHeight = window.innerHeight;
55 final top = e.offset.top;
56 final bottomMargin = 32;
57 final mainHeight = totalHeight - top - bottomMargin;
58 e.style.setProperty('height', '${mainHeight}px');
59 }
60
61 _insertLevels() {
62 SelectElement severityLevelSelector =
63 shadowRoot.querySelector(_kSeverityLevelSelector);
64 severityLevelSelector.children.clear();
65 _maxLevelLabelLength = 0;
66 for (var level in Level.LEVELS) {
67 var option = new OptionElement();
68 option.value = level.value.toString();
69 option.label = level.name;
70 if (level.name.length > _maxLevelLabelLength) {
71 _maxLevelLabelLength = level.name.length;
72 }
73 severityLevelSelector.children.add(option);
74 }
75 severityLevelSelector.selectedIndex = 0;
76 severityLevel = Level.ALL.value.toString();
77 }
78
79 _reset() {
80 logRecords.clear();
81 _unsub();
82 _sub();
83 _renderFull();
84 }
85
86 _unsub() {
87 cancelFutureSubscription(_loggingSubscriptionFuture);
88 _loggingSubscriptionFuture = null;
89 }
90
91 _sub() {
92 if (_loggingSubscriptionFuture != null) {
93 // Already subscribed.
94 return;
95 }
96 _loggingSubscriptionFuture =
97 app.vm.listenEventStream(Isolate.kLoggingStream, _onEvent);
98 }
99
100 _append(Map logRecord) {
101 logRecords.add(logRecord);
102 if (_shouldDisplay(logRecord)) {
103 // Queue for display.
104 pendingLogRecords.add(logRecord);
105 }
106 }
107
108 Element _renderAppend(Map logRecord) {
109 DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
110 var element = new DivElement();
111 element.classes.add('logItem');
112 element.classes.add(logRecord['level'].name);
113 element.appendText(
114 '${logRecord["level"].name.padLeft(_maxLevelLabelLength)} '
115 '${Utils.formatDateTime(logRecord["time"])} '
116 '${logRecord["message"].valueAsString}\n');
117 logContainer.children.add(element);
118 return element;
119 }
120
121 _renderFull() {
122 DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
123 logContainer.children.clear();
124 pendingLogRecords.clear();
125 for (var logRecord in logRecords) {
126 if (_shouldDisplay(logRecord)) {
127 _renderAppend(logRecord);
128 }
129 }
130 _scrollToBottom(logContainer);
131 }
132
133 /// Is [container] scrolled to the within [threshold] pixels of the bottom?
134 static bool _isScrolledToBottom(DivElement container, [int threshold = 2]) {
135 if (container == null) {
136 return false;
137 }
138 // scrollHeight -> complete height of element including scrollable area.
139 // clientHeight -> height of element on page.
140 // scrollTop -> how far is an element scrolled (from 0 to scrollHeight).
141 final distanceFromBottom =
142 container.scrollHeight - container.clientHeight - container.scrollTop;
143 const threshold = 2; // 2 pixel slop.
144 return distanceFromBottom <= threshold;
145 }
146
147 /// Scroll [container] so the bottom content is visible.
148 static _scrollToBottom(DivElement container) {
149 if (container == null) {
150 return;
151 }
152 // Adjust scroll so that the bottom of the content is visible.
153 container.scrollTop = container.scrollHeight - container.clientHeight;
154 }
155
156 _flushPendingLogs() {
157 DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
158 bool autoScroll = _isScrolledToBottom(logContainer);
159 for (var logRecord in pendingLogRecords) {
160 _renderAppend(logRecord);
161 }
162 if (autoScroll) {
163 _scrollToBottom(logContainer);
164 }
165 pendingLogRecords.clear();
166 }
167
168 _onEvent(ServiceEvent event) {
169 assert(event.kind == Isolate.kLoggingStream);
170 _append(event.logRecord);
171 }
172
173 void isolateChanged(oldValue) {
174 _reset();
175 }
176
177 void severityLevelChanged(oldValue) {
178 _severityLevelValue = int.parse(severityLevel);
179 _renderFull();
180 }
181
182 Future clear() {
183 logRecords.clear();
184 pendingLogRecords.clear();
185 _renderFull();
186 return new Future.value(null);
187 }
188
189 bool _shouldDisplay(Map logRecord) {
190 return logRecord['level'].value >= _severityLevelValue;
191 }
192
193 @observable Isolate isolate;
194 @observable String severityLevel;
195 int _severityLevelValue = 0;
196 int _maxLevelLabelLength = 0;
197 Future<StreamSubscription> _loggingSubscriptionFuture;
198 StreamSubscription _resizeSubscription;
199 final List<Map> logRecords = new List<Map>();
200 final List<Map> pendingLogRecords = new List<Map>();
201 } 132 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/elements/css/shared.css ('k') | runtime/observatory/lib/src/elements/logging.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698