diff --git a/README.md b/README.md index 410bf8d..50af80a 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,59 @@ # ember-appmetrics -This README outlines the details of collaborating on this Ember addon. +[![Build Status](https://travis-ci.org/gokatz/ember-appmetrics.svg?branch=master)](https://travis-ci.org/gokatz/ember-appmetrics) + +The ember version of [appmetrics.js](https://github.com/ebidel/appmetrics.js). Used to measure various things in your Ember app with ever simple APIs. + +## Installation +For Ember CLI >= `0.2.3`: +```shell +ember install ember-appmetrics +``` +For Ember CLI < `0.2.3`: +```shell +ember install:addon ember-appmetrics +``` + +## Compatibility +This addon is tested against the latest stable Ember version. + +## Usage + +Inject the metrics service like `'metrics: Ember.inject.service()'` into the class where you want to measure the performance or use initializers if you are going with one-time injection. + +Addon provides three API to measure the performace of a given period. +- `start` : need to call this api with an event name as argument to mark the starting point +- `end` : need to call this api with an event name as argument to mark the ending point +- `measure` : will return the calculated time for the given event + +```js + this.get('metric').start('accounts_page'); + Ember.run.scheduleOnce('afterRender', () => { + this.get('metric').end('accounts_page'); + let accountsPageRenderDuration = this.get('metric').measure('accounts_page'); + console.log(accountsPageRenderDuration); // will return the duration to for this render performance in milliseconds. + }); +``` + +## Browser support + +Since fall back machanism of all level has been handled in addon itself, the only thing addon needs is that the browser must have Date API, which is supported in all major and minor browsers. + +PS: In Safari, the User Timing API (performance.mark()) is not available, so the DevTools timeline will not be annotated with marks. ## Installation -* `git clone ` this repository -* `cd ember-appmetrics` +* `git clone` this repository * `npm install` * `bower install` ## Running -* `ember serve` -* Visit your app at [http://localhost:4200](http://localhost:4200). +* `ember server` +* Visit your app at http://localhost:4200. ## Running Tests -* `npm test` (Runs `ember try:each` to test your addon against multiple Ember versions) * `ember test` * `ember test --server` @@ -24,4 +61,4 @@ This README outlines the details of collaborating on this Ember addon. * `ember build` -For more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/). +For more information on using ember-cli, visit [http://www.ember-cli.com/](http://www.ember-cli.com/). diff --git a/addon/services/metrics.js b/addon/services/metrics.js new file mode 100644 index 0000000..28b06c0 --- /dev/null +++ b/addon/services/metrics.js @@ -0,0 +1,91 @@ +import Ember from 'ember'; + +const { typeOf } = Ember; + +export default Ember.Service.extend({ + isMarkSupportedBrowser: true, + isNowSupportedBrowser: true, + + secondaryPerformanceObj: {}, + + init() { + if (!(window.performance && window.performance.mark)) { + console.log('Performance.mark is not supported in this browser. Hence falling back to performance.now()'); + this.set('isMarkSupportedBrowser', false); + + if (!(window.performance && window.performance.now)) { + console.log('Performance.now is also not supported. Hence falling back to javascript Date API'); + this.set('isNowSupportedBrowser', false); + + } + } + }, + + start(eventName) { + let secondaryPerformanceObj = this.get('secondaryPerformanceObj'); + secondaryPerformanceObj[eventName] = secondaryPerformanceObj[eventName] || {}; + let eventObj = secondaryPerformanceObj[eventName]; + + if (typeOf(eventName) !== 'string') { + throw 'Expected type String for invoking `start`'; + } + + if (this.get('isNowSupportedBrowser')) { + if (this.get('isMarkSupportedBrowser')) { + performance.mark(`mark_${eventName}_start`); + } else { + eventObj.start = window.performance.now(); + } + } else { + eventObj.start = new Date().valueOf(); + } + + return; + }, + + end(eventName) { + let secondaryPerformanceObj = this.get('secondaryPerformanceObj'); + + secondaryPerformanceObj[eventName] = secondaryPerformanceObj[eventName] || {}; + let eventObj = secondaryPerformanceObj[eventName]; + + if (typeOf(eventName) !== 'string') { + throw 'Expected type String for invoking `end`'; + } + + if (this.get('isNowSupportedBrowser')) { + let startMark = `mark_${eventName}_start`; + let endMark = `mark_${eventName}_end`; + + if (this.get('isMarkSupportedBrowser')) { + performance.mark(endMark); + performance.measure(eventName, startMark, endMark); + } else { + eventObj.end = window.performance.now(); + } + } else { + eventObj.end = new Date().valueOf(); + } + return; + }, + + measure(eventName) { + let secondaryPerformanceObj = this.get('secondaryPerformanceObj'); + let eventObj = secondaryPerformanceObj[eventName] || {}; + let duration; + + if (this.get('isMarkSupportedBrowser')) { + let perfEntries = performance.getEntriesByName(eventName); + // poping up the last entry pushed into teh array + let entry = perfEntries[perfEntries.length - 1]; + if (entry) { + duration = entry.duration; + } + } else { + duration = eventObj.end - eventObj.start; + } + + return duration || -1; + } + +}); diff --git a/app/services/metrics.js b/app/services/metrics.js new file mode 100644 index 0000000..5fd5fe6 --- /dev/null +++ b/app/services/metrics.js @@ -0,0 +1 @@ +export { default } from 'ember-appmetrics/services/metrics'; diff --git a/package.json b/package.json index 3b2de56..0e1f6c4 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { "name": "ember-appmetrics", - "version": "0.0.0", + "version": "0.1.0", "description": "The default blueprint for ember-cli addons.", "keywords": [ "ember-addon" ], "license": "MIT", - "author": "", + "author": "Gokul Kathirvel (@_gokatz)", "directories": { "doc": "doc", "test": "tests" }, - "repository": "", + "repository": "https://github.com/gokatz/ember-appmetrics", "scripts": { "build": "ember build", "start": "ember server", @@ -40,7 +40,6 @@ "ember-export-application-global": "^1.0.5", "ember-load-initializers": "^0.5.1", "ember-resolver": "^2.0.3", - "ember-welcome-page": "^1.0.3", "loader.js": "^4.0.10" }, "engines": { diff --git a/tests/unit/services/metrics-test.js b/tests/unit/services/metrics-test.js new file mode 100644 index 0000000..9efe133 --- /dev/null +++ b/tests/unit/services/metrics-test.js @@ -0,0 +1,12 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('service:metrics', 'Unit | Service | metrics', { + // Specify the other units that are required for this test. + // needs: ['service:foo'] +}); + +// Replace this with your real tests. +test('it exists', function(assert) { + let service = this.subject(); + assert.ok(service); +});