ember-metrics
Advanced tools
Comparing version 0.1.5 to 0.2.0
@@ -7,17 +7,48 @@ import Ember from 'ember'; | ||
assert, | ||
isNone, | ||
warn, | ||
get, | ||
set, | ||
merge, | ||
A: emberArray, | ||
String: { dasherize } | ||
} = Ember; | ||
const { keys } = Object; | ||
export default Service.extend({ | ||
_adapters: {}, | ||
/** | ||
* Cached adapters to reduce multiple expensive lookups. | ||
* | ||
* @property _adapters | ||
* @private | ||
* @type Object | ||
* @default null | ||
*/ | ||
_adapters: null, | ||
/** | ||
* Contextual information attached to each call to an adapter. Often you'll | ||
* want to include things like `currentUser.name` with every event or page | ||
* view that's tracked. Any properties that you bind to `metrics.context` | ||
* will be merged into the options for every service call. | ||
* | ||
* @property context | ||
* @type Object | ||
* @default null | ||
*/ | ||
context: null, | ||
/** | ||
* When the Service is created, activate adapters that were specified in the | ||
* configuration. This config is injected into the Service as | ||
* `metricsAdapters`. | ||
* | ||
* @method init | ||
* @param {Void} | ||
* @return {Void} | ||
*/ | ||
init() { | ||
const adapters = getWithDefault(this, 'metricsAdapters', emberArray([])); | ||
set(this, '_adapters', {}); | ||
set(this, 'context', {}); | ||
this.activateAdapters(adapters); | ||
this._super(...arguments); | ||
this.activateAdapters(adapters); | ||
}, | ||
@@ -41,17 +72,18 @@ | ||
/** | ||
* Instantiates the adapters specified in the configuration and caches them | ||
* for future retrieval. | ||
* | ||
* @method activateAdapters | ||
* @param {Array} adapterOptions | ||
* @return {Object} instantiated adapters | ||
*/ | ||
activateAdapters(adapterOptions = []) { | ||
const cachedAdapters = get(this, '_adapters'); | ||
let activatedAdapters = {}; | ||
const activatedAdapters = {}; | ||
adapterOptions.forEach((adapterOption) => { | ||
const { name } = adapterOption; | ||
let adapter; | ||
const adapter = cachedAdapters[name] ? cachedAdapters[name] : this._activateAdapter(adapterOption); | ||
if (cachedAdapters[name]) { | ||
warn(`[ember-metrics] Metrics adapter ${name} has already been activated.`); | ||
adapter = cachedAdapters[name]; | ||
} else { | ||
adapter = this._activateAdapter(adapterOption); | ||
} | ||
set(activatedAdapters, name, adapter); | ||
@@ -63,37 +95,65 @@ }); | ||
/** | ||
* Invokes a method across all activated adapters. | ||
* | ||
* @method invoke | ||
* @param {String} methodName | ||
* @param {Rest} args | ||
* @return {Void} | ||
*/ | ||
invoke(methodName, ...args) { | ||
const adaptersObj = get(this, '_adapters'); | ||
const adapterNames = Object.keys(adaptersObj); | ||
const cachedAdapters = get(this, '_adapters'); | ||
const allAdapterNames = keys(cachedAdapters); | ||
const [selectedAdapterNames, options] = args.length > 1 ? [[args[0]], args[1]] : [allAdapterNames, args[0]]; | ||
const mergedOptions = merge(get(this, 'context'), options); | ||
const adapters = adapterNames.map((adapterName) => { | ||
return get(adaptersObj, adapterName); | ||
}); | ||
selectedAdapterNames | ||
.map((adapterName) => get(cachedAdapters, adapterName)) | ||
.forEach((adapter) => adapter[methodName](mergedOptions)); | ||
}, | ||
if (args.length > 1) { | ||
let [ adapterName, options ] = args; | ||
const adapter = get(adaptersObj, adapterName); | ||
/** | ||
* On teardown, destroy cached adapters together with the Service. | ||
* | ||
* @method willDestroy | ||
* @param {Void} | ||
* @return {Void} | ||
*/ | ||
willDestroy() { | ||
const cachedAdapters = get(this, '_adapters'); | ||
adapter[methodName](options); | ||
} else { | ||
adapters.forEach((adapter) => { | ||
adapter[methodName](...args); | ||
}); | ||
for (let adapterName in cachedAdapters) { | ||
get(cachedAdapters, adapterName).destroy(); | ||
} | ||
}, | ||
_activateAdapter(adapterOption = {}) { | ||
const metrics = this; | ||
const { name, config } = adapterOption; | ||
/** | ||
* Instantiates an adapter if one is found. | ||
* | ||
* @method _activateAdapter | ||
* @param {Object} | ||
* @private | ||
* @return {Adapter} | ||
*/ | ||
_activateAdapter({ name, config } = {}) { | ||
const Adapter = this._lookupAdapter(name); | ||
assert(`[ember-metrics] Could not find metrics adapter ${name}.`, Adapter); | ||
return Adapter.create({ metrics, config }); | ||
return Adapter.create({ this, config }); | ||
}, | ||
_lookupAdapter(adapterName = '') { | ||
const container = get(this, 'container'); | ||
/** | ||
* Looks up the adapter from the container. Prioritizes the consuming app's | ||
* adapters over the addon's adapters. | ||
* | ||
* @method _lookupAdapter | ||
* @param {String} adapterName | ||
* @private | ||
* @return {Adapter} a local adapter or an adapter from the addon | ||
*/ | ||
_lookupAdapter(adapterName) { | ||
const { container } = this; | ||
if (isNone(container)) { | ||
return; | ||
} | ||
assert('[ember-metrics] The service is missing its container.', container); | ||
assert('[ember-metrics] Could not find metrics adapter without a name.', adapterName); | ||
@@ -103,14 +163,5 @@ const dasherizedAdapterName = dasherize(adapterName); | ||
const localAdapter = container.lookupFactory(`metrics-adapter:${dasherizedAdapterName}`); | ||
const adapter = localAdapter ? localAdapter : availableAdapter; | ||
return adapter; | ||
}, | ||
willDestroy() { | ||
const adapters = get(this, '_adapters'); | ||
for (let adapterName in adapters) { | ||
get(adapters, adapterName).destroy(); | ||
} | ||
return localAdapter ? localAdapter : availableAdapter; | ||
} | ||
}); |
{ | ||
"name": "ember-metrics", | ||
"version": "0.1.5", | ||
"version": "0.2.0", | ||
"description": "Send data to multiple analytics integrations without re-implementing new API", | ||
@@ -55,3 +55,5 @@ "directories": { | ||
"tracking", | ||
"google analytics" | ||
"google analytics", | ||
"google tag manager", | ||
"mixpanel" | ||
], | ||
@@ -58,0 +60,0 @@ "dependencies": { |
@@ -81,3 +81,3 @@ # ember-metrics | ||
```js | ||
/** | ||
/** | ||
* @param {String} name Adapter name | ||
@@ -146,2 +146,10 @@ * @param {Object} config Configuration options for the service | ||
#### Context | ||
Often, you may want to include information like the current user's name with every event or page view that's tracked. Any properties that are set on `metrics.context` will be merged into options for every Service call. | ||
```js | ||
Ember.set(this, 'metrics.context.userName', 'Jimbo'); | ||
Ember.get(this, 'metrics').trackPage({ page: 'page/1' }); // { userName: 'Jimbo', page: 'page/1' } | ||
``` | ||
### API | ||
@@ -153,16 +161,16 @@ | ||
- `trackPage([analyticsName], options)` | ||
- `trackPage([analyticsName], options)` | ||
This is commonly used by analytics services to track page views. Due to the way Single Page Applications implement routing, you will need to call this on the `activate` hook of each route to track all page views. | ||
- `trackEvent([analyticsName], options)` | ||
This is a general purpose method for tracking a named event in your application. | ||
- `identify([analyticsName], options)` | ||
For analytics services that have identification functionality. | ||
- `alias([analyticsName], options)` | ||
For services that implement it, this method notifies the analytics service that an anonymous user now has a unique identifier. | ||
@@ -191,3 +199,3 @@ | ||
To add an attribute, just prefix it with `metrics` and enter it in camelcase. | ||
To add an attribute, just prefix it with `metrics` and enter it in camelcase. | ||
@@ -229,3 +237,3 @@ ### Lazy Initialization | ||
This creates `app/metrics-adapters/foo-bar.js` and a unit test at `tests/unit/metrics-adapters/foo-bar-test.js`, which you should now customize. | ||
This creates `app/metrics-adapters/foo-bar.js` and a unit test at `tests/unit/metrics-adapters/foo-bar-test.js`, which you should now customize. | ||
@@ -232,0 +240,0 @@ ### Required Methods |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29767
8264
576
304