Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(@aws-amplify/analytics): Analytics Typescript updates #9272

Merged
merged 9 commits into from
Feb 10, 2022
85 changes: 57 additions & 28 deletions packages/analytics/src/Analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ import {
} from '@aws-amplify/core';
import { AWSPinpointProvider } from './Providers/AWSPinpointProvider';

import { AnalyticsProvider, EventMetrics } from './types';
import {
AnalyticsProvider,
EventAttributes,
EventMetrics,
AnalyticsEvent,
AutoTrackOpts,
} from './types';
import { PageViewTracker, EventTracker, SessionTracker } from './trackers';

const logger = new Logger('AnalyticsClass');
Expand All @@ -45,6 +51,8 @@ const trackers = {
session: SessionTracker,
};

type TrackerTypes = keyof typeof trackers;
type Trackers = typeof trackers[TrackerTypes];
let _instance = null;

/**
Expand All @@ -53,8 +61,8 @@ let _instance = null;
export class AnalyticsClass {
private _config;
private _pluggables: AnalyticsProvider[];
private _disabled;
private _trackers;
private _disabled: boolean;
private _trackers: Trackers;

/**
* Initialize Analtyics
Expand All @@ -64,7 +72,6 @@ export class AnalyticsClass {
this._config = {};
this._pluggables = [];
this._disabled = false;
this._trackers = {};
_instance = this;

this.record = this.record.bind(this);
Expand Down Expand Up @@ -100,7 +107,7 @@ export class AnalyticsClass {
this._config['autoSessionRecord'] = true;
}

this._pluggables.forEach((pluggable) => {
this._pluggables.forEach(pluggable => {
// for backward compatibility
const providerConfig =
pluggable.getProviderName() === 'AWSPinpoint' &&
Expand Down Expand Up @@ -130,7 +137,7 @@ export class AnalyticsClass {

/**
* add plugin into Analytics category
* @param {Object} pluggable - an instance of the plugin
* @param pluggable - an instance of the plugin
*/
public addPluggable(pluggable: AnalyticsProvider) {
if (pluggable && pluggable.getCategory() === 'Analytics') {
Expand All @@ -149,9 +156,9 @@ export class AnalyticsClass {

/**
* Get the plugin object
* @param providerName - the name of the plugin
* @param providerName - the name of the provider to be removed
*/
public getPluggable(providerName) {
public getPluggable(providerName: string): AnalyticsProvider {
for (let i = 0; i < this._pluggables.length; i += 1) {
const pluggable = this._pluggables[i];
if (pluggable.getProviderName() === providerName) {
Expand All @@ -165,9 +172,9 @@ export class AnalyticsClass {

/**
* Remove the plugin object
* @param providerName - the name of the plugin
* @param providerName - the name of the provider to be removed
*/
public removePluggable(providerName) {
public removePluggable(providerName: string): void {
let idx = 0;
while (idx < this._pluggables.length) {
if (this._pluggables[idx].getProviderName() === providerName) {
Expand Down Expand Up @@ -201,6 +208,7 @@ export class AnalyticsClass {

/**
* Record Session start
* @param [provider] - name of the provider.
* @return - A promise which resolves if buffer doesn't overflow
*/
public async startSession(provider?: string) {
Expand All @@ -210,6 +218,7 @@ export class AnalyticsClass {

/**
* Record Session stop
* @param [provider] - name of the provider.
* @return - A promise which resolves if buffer doesn't overflow
*/
public async stopSession(provider?: string) {
Expand All @@ -219,14 +228,26 @@ export class AnalyticsClass {

/**
* Record one analytic event and send it to Pinpoint
* @param {String} name - The name of the event
* @param {Object} [attributes] - Attributes of the event
* @param {Object} [metrics] - Event metrics
* @param event - An object with the name of the event, attributes of the event and event metrics.
* @param [provider] - name of the provider.
*/
public async record(event: AnalyticsEvent, provider?: string);
/**
* Record one analytic event and send it to Pinpoint
* @deprecated Use the new syntax and pass in the event as an object instead.
* @param eventName - The name of the event
* @param [attributes] - Attributes of the event
* @param [metrics] - Event metrics
* @return - A promise which resolves if buffer doesn't overflow
*/
public async record(
event: string | object,
provider?,
eventName: string,
attributes?: EventAttributes,
metrics?: EventMetrics
);
Comment on lines 243 to +247
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this something we allow too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is the old way of using Analytics.record (at least from the implementation, this is supported)

Copy link
Contributor

@ashika01 ashika01 Dec 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha. I dont see documentation on it. Do u think we can add this usage in docs with a deprecation notice?

public async record(
event: string | AnalyticsEvent,
providerOrAttributes?: string | EventAttributes,
metrics?: EventMetrics
) {
let params = null;
Expand All @@ -235,24 +256,27 @@ export class AnalyticsClass {
params = {
event: {
name: event,
attributes: provider,
attributes: providerOrAttributes,
metrics,
},
provider: 'AWSPinpoint',
};
} else {
params = { event, provider };
params = { event, provider: providerOrAttributes };
}
return this._sendEvent(params);
}

public async updateEndpoint(attrs, provider?) {
public async updateEndpoint(
attrs: { [key: string]: any },
provider?: string
) {
const event = { ...attrs, name: '_update_endpoint' };

return this.record(event, provider);
}

private _sendEvent(params) {
private _sendEvent(params: { event: AnalyticsEvent; provider?: string }) {
if (this._disabled) {
logger.debug('Analytics has been disabled');
return Promise.resolve();
Expand All @@ -261,15 +285,20 @@ export class AnalyticsClass {
const provider = params.provider ? params.provider : 'AWSPinpoint';

return new Promise((resolve, reject) => {
this._pluggables.forEach((pluggable) => {
this._pluggables.forEach(pluggable => {
if (pluggable.getProviderName() === provider) {
pluggable.record(params, { resolve, reject });
}
});
});
}

public autoTrack(trackerType, opts) {
/**
* Enable or disable auto tracking
* @param trackerType - The type of tracker to activate.
* @param [opts] - Auto tracking options.
*/
public autoTrack(trackerType: TrackerTypes, opts: AutoTrackOpts) {
if (!trackers[trackerType]) {
logger.debug('invalid tracker type');
return;
Expand All @@ -295,7 +324,7 @@ export class AnalyticsClass {
let endpointUpdated = false;
let authConfigured = false;
let analyticsConfigured = false;
const listener = (capsule) => {
const listener = capsule => {
const { channel, payload } = capsule;
logger.debug('on hub capsule ' + channel, payload);

Expand All @@ -314,7 +343,7 @@ const listener = (capsule) => {
}
};

const storageEvent = (payload) => {
const storageEvent = payload => {
const {
data: { attrs, metrics },
} = payload;
Expand All @@ -327,19 +356,19 @@ const storageEvent = (payload) => {
attributes: attrs,
metrics,
})
.catch((e) => {
.catch(e => {
logger.debug('Failed to send the storage event automatically', e);
});
}
};

const authEvent = (payload) => {
const authEvent = payload => {
const { event } = payload;
if (!event) {
return;
}

const recordAuthEvent = async (eventName) => {
const recordAuthEvent = async eventName => {
if (authConfigured && analyticsConfigured) {
try {
return await _instance.record({ name: `_userauth.${eventName}` });
Expand Down Expand Up @@ -370,7 +399,7 @@ const authEvent = (payload) => {
}
};

const analyticsEvent = (payload) => {
const analyticsEvent = payload => {
const { event } = payload;
if (!event) return;

Expand All @@ -387,7 +416,7 @@ const analyticsEvent = (payload) => {
const sendEvents = () => {
const config = _instance.configure();
if (!endpointUpdated && config['autoSessionRecord']) {
_instance.updateEndpoint({ immediate: true }).catch((e) => {
_instance.updateEndpoint({ immediate: true }).catch(e => {
logger.debug('Failed to update the endpoint', e);
});
endpointUpdated = true;
Expand Down
14 changes: 13 additions & 1 deletion packages/analytics/src/types/Analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
* and limitations under the License.
*/
import { ICredentials } from '@aws-amplify/core';

/**
* Analytics instance options
*/
Expand Down Expand Up @@ -59,3 +58,16 @@ export interface SessionTrackOpts {
| (() => EventAttributes | Promise<EventAttributes>);
provider?: string;
}

export interface AutoTrackOpts {
enable: boolean;
attributes?: EventAttributes;
provider?: string;
}

export interface AnalyticsEvent {
name: string;
attributes?: EventAttributes;
metrics?: EventMetrics;
immediate?: boolean;
}