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

Unified Diff: runtime/observatory/lib/src/elements/logging.dart

Issue 1250853006: Logging page (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: runtime/observatory/lib/src/elements/logging.dart
diff --git a/runtime/observatory/lib/src/elements/logging.dart b/runtime/observatory/lib/src/elements/logging.dart
new file mode 100644
index 0000000000000000000000000000000000000000..6e22aadb387e6dfeb6a25938b40d525e987a7b01
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/logging.dart
@@ -0,0 +1,202 @@
+// Copyright (c) 2015, 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.
+
+library logging_page;
+
+import 'dart:async';
+import 'dart:html';
+import 'observatory_element.dart';
+import 'package:logging/logging.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/app.dart';
+import 'package:observatory/elements.dart';
+import 'package:observatory/utils.dart';
+import 'package:polymer/polymer.dart';
+
+@CustomTag('logging-page')
+class LoggingPageElement extends ObservatoryElement {
+ static const _kPageSelector = '#page';
+ static const _kLogSelector = '#log';
+ static const _kSeverityLevelSelector = '#severityLevelSelector';
+
+ LoggingPageElement.created() : super.created();
+
+ domReady() {
+ super.domReady();
+ _insertLevels();
+ }
+
+ attached() {
+ super.attached();
+ _sub();
+ _resizeSubscription = window.onResize.listen((_) => _updatePageHeight());
+ _updatePageHeight();
+ // Turn on the periodic poll timer for this page.
+ pollPeriod = const Duration(milliseconds:100);
+ }
+
+ detached() {
+ super.detached();
+ if (_resizeSubscription != null) {
+ _resizeSubscription.cancel();
+ _resizeSubscription = null;
+ }
+ _unsub();
+ }
+
+ void onPoll() {
+ _flushPendingLogs();
+ }
+
+ _updatePageHeight() {
+ HtmlElement e = shadowRoot.querySelector(_kPageSelector);
+ final totalHeight = window.innerHeight;
+ final top = e.offset.top;
+ final bottomMargin = 32;
+ final mainHeight = totalHeight - top - bottomMargin;
+ e.style.setProperty('height', '${mainHeight}px');
+ }
+
+ _insertLevels() {
+ SelectElement severityLevelSelector =
+ shadowRoot.querySelector(_kSeverityLevelSelector);
+ severityLevelSelector.children.clear();
+ _maxLevelLabelLength = 0;
+ for (var level in Level.LEVELS) {
+ var option = new OptionElement();
+ option.value = level.value.toString();
+ option.label = level.name;
+ if (level.name.length > _maxLevelLabelLength) {
+ _maxLevelLabelLength = level.name.length;
+ }
+ severityLevelSelector.children.add(option);
+ }
+ severityLevelSelector.selectedIndex = 0;
+ severityLevel = Level.ALL.value.toString();
+ }
+
+ _reset() {
+ logRecords.clear();
+ _unsub();
+ _sub();
+ _renderFull();
+ }
+
+ _unsub() {
+ cancelFutureSubscription(_loggingSubscriptionFuture);
+ _loggingSubscriptionFuture = null;
+ }
+
+ _sub() {
+ if (_loggingSubscriptionFuture != null) {
+ // Already subscribed.
+ return;
+ }
+ _loggingSubscriptionFuture =
+ app.vm.listenEventStream(Isolate.kLoggingStream, _onEvent);
+ }
+
+ _append(Map logRecord) {
+ logRecords.add(logRecord);
+ if (_shouldDisplay(logRecord)) {
+ // Queue for display.
+ pendingLogRecords.add(logRecord);
+ }
+ }
+
+ Element _renderAppend(Map logRecord) {
+ DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
+ var element = new DivElement();
+ element.classes.add('logItem');
+ element.classes.add(logRecord['level'].name);
+ element.appendText(
+ '${logRecord["level"].name.padLeft(_maxLevelLabelLength)} '
+ '${Utils.formatDateTime(logRecord["time"])} '
+ '${logRecord["message"].valueAsString}\n');
+ logContainer.children.add(element);
+ return element;
+ }
+
+ _renderFull() {
+ DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
+ logContainer.children.clear();
+ pendingLogRecords.clear();
+ for (var logRecord in logRecords) {
+ if (_shouldDisplay(logRecord)) {
+ _renderAppend(logRecord);
+ }
+ }
+ _scrollToBottom(logContainer);
+ }
+
+ /// Is [container] scrolled to the within [threshold] pixels of the bottom?
+ static bool _isScrolledToBottom(DivElement container, [int threshold = 2]) {
+ if (container == null) {
+ return false;
+ }
+ // scrollHeight -> complete height of element including scrollable area.
+ // clientHeight -> height of element on page.
+ // scrollTop -> how far is an element scrolled (from 0 to scrollHeight).
+ final distanceFromBottom =
+ container.scrollHeight - container.clientHeight - container.scrollTop;
+ const threshold = 2; // 2 pixel slop.
+ return distanceFromBottom <= threshold;
+ }
+
+ /// Scroll [container] so the bottom content is visible.
+ static _scrollToBottom(DivElement container) {
+ if (container == null) {
+ return;
+ }
+ // Adjust scroll so that the bottom of the content is visible.
+ container.scrollTop = container.scrollHeight - container.clientHeight;
+ }
+
+ _flushPendingLogs() {
+ DivElement logContainer = shadowRoot.querySelector(_kLogSelector);
+ bool autoScroll = _isScrolledToBottom(logContainer);
+ var lastElement;
+ for (var logRecord in pendingLogRecords) {
+ lastElement = _renderAppend(logRecord);
+ }
+ if (autoScroll) {
+ _scrollToBottom(logContainer);
+ }
+ pendingLogRecords.clear();
+ }
+
+ _onEvent(ServiceEvent event) {
+ assert(event.kind == Isolate.kLoggingStream);
+ _append(event.logRecord);
+ }
+
+ void isolateChanged(oldValue) {
+ _reset();
+ }
+
+ void severityLevelChanged(oldValue) {
+ _severityLevelValue = int.parse(severityLevel);
+ _renderFull();
+ }
+
+ Future clear() {
+ logRecords.clear();
+ pendingLogRecords.clear();
+ _renderFull();
+ return new Future.value(null);
+ }
+
+ bool _shouldDisplay(Map logRecord) {
+ return logRecord['level'].value >= _severityLevelValue;
+ }
+
+ @observable Isolate isolate;
+ @observable String severityLevel;
+ int _severityLevelValue = 0;
+ int _maxLevelLabelLength = 0;
+ Future<StreamSubscription> _loggingSubscriptionFuture;
+ StreamSubscription _resizeSubscription;
+ final List<Map> logRecords = new List<Map>();
+ final List<Map> pendingLogRecords = new List<Map>();
+}
« no previous file with comments | « runtime/observatory/lib/src/elements/isolate_summary.html ('k') | runtime/observatory/lib/src/elements/logging.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698