<commit_before>// 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 'dart:convert';

import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'package:vm_service_lib/vm_service_lib.dart';

import '../framework/framework.dart';
import '../globals.dart';
import '../tables.dart';
import '../timeline/fps.dart';
import '../ui/elements.dart';
import '../utils.dart';

// TODO(devoncarew): inspect calls

// TODO(devoncarew): filtering, and enabling additional logging

// TODO(devoncarew): don't update DOM when we're not active; update once we return

// For performance reasons, we drop old logs in batches, so the log will grow
// to kMaxLogItemsUpperBound then truncate to kMaxLogItemsLowerBound.
const int kMaxLogItemsLowerBound = 5000;
const int kMaxLogItemsUpperBound = 5500;
DateFormat timeFormat = new DateFormat('HH:mm:ss.SSS');

class LoggingScreen extends Screen {
  Table<LogData> loggingTable;
  StatusItem logCountStatus;
  SetStateMixin loggingStateMixin = new SetStateMixin();

  LoggingScreen()
      : super(name: 'Logs', id: 'logs', iconClass: 'octicon-clippy') {
    logCountStatus = new StatusItem();
    logCountStatus.element.text = '';
    addStatusItem(logCountStatus);

    serviceInfo.onConnectionAvailable.listen(_handleConnectionStart);
    if (serviceInfo.hasConnection) {
      _handleConnectionStart(serviceInfo.service);
    }
    serviceInfo.onConnectionClosed.listen(_handleConnectionStop);
  }

  @override
  void createContent(Framework framework, CoreElement mainDiv) {
    this.framework = framework;

    LogDetailsUI logDetailsUI;

    mainDiv.add(<CoreElement>[
      _createTableView()
        ..clazz('section')
        ..flex(),
      div(c: 'section')
        ..layoutVertical()
        ..add(logDetailsUI = new LogDetailsUI()),
    ]);

    loggingTable.onSelect.listen((LogData selection) {
      logDetailsUI.setData(selection);
    });
  }

  CoreElement _createTableView() {
    loggingTable = new Table<LogData>.virtual(isReversed: true);

    loggingTable.addColumn(new LogWhenColumn());
    loggingTable.addColumn(new LogKindColumn());
    loggingTable.addColumn(new LogMessageColumn());

    loggingTable.setRows(data);

    _updateStatus();

    return loggingTable.element;
  }

  void _updateStatus() {
    final int count = loggingTable.rows.length;
    logCountStatus.element.text = '${nf.format(count)} events';
  }

  @override
  HelpInfo get helpInfo =>
      new HelpInfo(title: 'logs view docs', url: 'http://www.cheese.com');

  void _handleConnectionStart(VmService service) {
    if (ref == null) {
      return;
    }

    // TODO(devoncarew): Add support for additional events, like 'inspect', ...

    // Log stdout events.
    service.onStdoutEvent.listen((Event e) {
      final String message = decodeBase64(e.bytes);<commit_msg>Cap "x events" label at the min bound and add a + to the end (#28)<commit_after>// 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 'dart:convert';

import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'package:vm_service_lib/vm_service_lib.dart';

import '../framework/framework.dart';
import '../globals.dart';
import '../tables.dart';
import '../timeline/fps.dart';
import '../ui/elements.dart';
import '../utils.dart';

// TODO(devoncarew): inspect calls

// TODO(devoncarew): filtering, and enabling additional logging

// TODO(devoncarew): don't update DOM when we're not active; update once we return

// For performance reasons, we drop old logs in batches, so the log will grow
// to kMaxLogItemsUpperBound then truncate to kMaxLogItemsLowerBound.
const int kMaxLogItemsLowerBound = 5000;
const int kMaxLogItemsUpperBound = 5500;
DateFormat timeFormat = new DateFormat('HH:mm:ss.SSS');

class LoggingScreen extends Screen {
  Table<LogData> loggingTable;
  StatusItem logCountStatus;
  SetStateMixin loggingStateMixin = new SetStateMixin();

  LoggingScreen()
      : super(name: 'Logs', id: 'logs', iconClass: 'octicon-clippy') {
    logCountStatus = new StatusItem();
    logCountStatus.element.text = '';
    addStatusItem(logCountStatus);

    serviceInfo.onConnectionAvailable.listen(_handleConnectionStart);
    if (serviceInfo.hasConnection) {
      _handleConnectionStart(serviceInfo.service);
    }
    serviceInfo.onConnectionClosed.listen(_handleConnectionStop);
  }

  @override
  void createContent(Framework framework, CoreElement mainDiv) {
    this.framework = framework;

    LogDetailsUI logDetailsUI;

    mainDiv.add(<CoreElement>[
      _createTableView()
        ..clazz('section')
        ..flex(),
      div(c: 'section')
        ..layoutVertical()
        ..add(logDetailsUI = new LogDetailsUI()),
    ]);

    loggingTable.onSelect.listen((LogData selection) {
      logDetailsUI.setData(selection);
    });
  }

  CoreElement _createTableView() {
    loggingTable = new Table<LogData>.virtual(isReversed: true);

    loggingTable.addColumn(new LogWhenColumn());
    loggingTable.addColumn(new LogKindColumn());
    loggingTable.addColumn(new LogMessageColumn());

    loggingTable.setRows(data);

    _updateStatus();

    return loggingTable.element;
  }

  void _updateStatus() {
    final int count = loggingTable.rows.length;
    final String label = count >= kMaxLogItemsLowerBound
        ? '${nf.format(kMaxLogItemsLowerBound)}+'
        : nf.format(count);
    logCountStatus.element.text = '$label events';
  }

  @override
  HelpInfo get helpInfo =>
      new HelpInfo(title: 'logs view docs', url: 'http://www.cheese.com');

  void _handleConnectionStart(VmService service) {
    if (ref == null) {
      return;
    }

    // TODO(devoncarew): Add support for additional events, like 'inspect', ...

    // Log stdout events.
    service.onStdoutEvent.listen((Event e) {
      final String message = decodeBase64(e.bytes);
{'fraction_non_alphanumeric': 0.1196567090278924, 'fraction_numerical': 0.004951312097705892, 'mean_word_length': 3.848, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '481692', 'n_tokens_mistral': 1847, 'n_tokens_neox': 1767, 'n_words': 446}