appmetrics.js icon indicating copy to clipboard operation
appmetrics.js copied to clipboard

ES6 modules

Open oliviertassinari opened this issue 7 years ago • 4 comments

It would be great to support it. For now, the best way I see to use this module is by copy-pasting the content into one of my files.

oliviertassinari avatar Sep 09 '16 21:09 oliviertassinari

Does import Metric from 'appmetrics.js' not work? I guess I need an export default?

ebidel avatar Sep 10 '16 02:09 ebidel

I have noticed several things to do to make it work:

  • Export the Metric class: export default Metric;
  • Point the main section of the package.json toward the right entry point. Right now, it's pointing toward "main": "./src/appmetrics.js". But it's very common to ignore the node_modules when using babel.

Here is the version I'm using:

// @flow weak

import warning from 'warning'; // Allow to remove the assertion code from production

const start = new WeakMap();
const end = new WeakMap();

//  Not sure why weren't private method.

/**
 * True if the the browser supports the Navigation Timing API.
 * @type {boolean}
 */
function supportsPerfNow() {
  return window.performance && window.performance.now;
}

/**
 * True if the the browser supports the User Timing API.
 * @type {boolean}
 */
function supportsPerfMark() {
  return window.performance && window.performance.mark;
}

// Inspired by https://github.com/ebidel/appmetrics.js
class Metric {
  /**
   * Returns the duration of the timing metric or -1 if there a measurement has
   * not been made.
   * @type {number}
   */
  get duration() {
    let duration;

    if (supportsPerfNow()) {
      duration = end.get(this) - start.get(this);
    }

    // Use User Timing API results if available, otherwise return
    // window.performance.now() fallback.
    if (supportsPerfMark()) {
      // Note: this assumes the user has made only one measurement for the given
      // name. Return the first one found.
      const entry = window.performance.getEntriesByName(this.name)[0];
      if (entry && entry.entryType !== 'measure') {
        duration = entry.duration;
      }
    }

    return duration || -1;
  }

  name = '';

  /**
   * @param {string} name A name for the metric.
   */
  constructor(name) {
    warning(name, 'Please provide a metric name');

    // Simplify it, I don't want to crash when the performance API is not supported.

    this.name = name;
  }

  /**
   * Call to begin a measurement.
   * @return {Metric} Instance of this object.
   */
  start() {
    if (start.get(this)) {
      warning(false, 'Recording already started.');
      return this;
    }

    if (supportsPerfNow()) {
      start.set(this, window.performance.now());
    }

    // Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
    if (supportsPerfMark()) {
      window.performance.mark(`mark_${this.name}_start`);
    }

    return this;
  }

  /**
   * Call to end a measurement.
   * @return {Metric} Instance of this object.
   */
  end() {
    if (end.get(this)) {
      warning(false, 'Recording already stopped.');
      return this;
    }

    if (supportsPerfNow()) {
      end.set(this, window.performance.now());
    }

    // Support: developer.mozilla.org/en-US/docs/Web/API/Performance/mark
    if (supportsPerfMark()) {
      const startMark = `mark_${this.name}_start`;
      const endMark = `mark_${this.name}_end`;
      window.performance.mark(endMark);
      window.performance.measure(this.name, startMark, endMark);
    }

    return this;
  }

  // Remove sendToAnalytics as I'm using different API based on the platfrom : cordova / browser.
}

export default Metric;

oliviertassinari avatar Sep 10 '16 09:09 oliviertassinari

I have been publishing that among other tools for my needs under browser-metrics.

oliviertassinari avatar Dec 18 '16 13:12 oliviertassinari

Any interest in sending a pr?

ebidel avatar Dec 18 '16 18:12 ebidel