/**
* Copyright© 2016, Oracle and/or its affiliates. All rights reserved.
*/
/**
* Callback invoked after successfully flushing analytics events.
* @callback Analytics~successCallback
* @deprecated Use promises instead
*/
/**
* Callback invoked on error.
* @callback Analytics~errorCallback
* @param statusCode {Number} Any HTTP status code returned from the server, if available.
* @param message {String} The HTTP payload from the server, if available, or an error message.
* @deprecated Use promises instead
*/
/**
*
* Class that provides analytics capabilities. Callers should use
* MobileBackend's [analytics]{@link MobileBackend#analytics} property.
* @constructor
* @global
*/
function Analytics(backend, platform, utils, logger) {
var _sessionId = null;
var _events = [];
/**
* Returns session ID for current session.
* @returns {String}
*/
this.getSessionId = function(){
return _sessionId;
};
this._getEvents = function(){
return _events;
};
/**
* Starts a new session. If one is in progress, then a new session will not be created.
*/
this.startSession = function () {
if (_sessionId === null) {
if(locationEnabled()){
platform.initGPSLocation();
}
_sessionId = utils.uuid();
this.logNamedEvent('sessionStart').type = 'system';
}
};
/**
* Ends a session if one exists.
* @param [successCallback] {Analytics~successCallback} Callback invoked on success (deprecated use promises instead).
* @param [errorCallback] {Analytics~errorCallback} Callback invoked on error (deprecated use promises instead).
* @return {Promise.<Undefined|NetworkResponse>}
*/
this.endSession = function (successCallback, errorCallback) {
if (_sessionId !== null) {
var _this = this;
_this.logNamedEvent("sessionEnd").type = "system";
logger.verbose('Deactivate a default session');
return this.flush().then(flushSuccess, flushError);
} else {
if(errorCallback){
errorCallback(500, 'Session ID is null');
return undefined;
} else {
return Promise.reject(new NetworkResponse(500, 'Session ID is null'));
}
}
function flushSuccess(){
_sessionId = null;
if(successCallback){
successCallback();
}
}
function flushError(exception){
if(errorCallback){
errorCallback(exception.statusCode, exception.data);
} else {
return Promise.reject(exception);
}
}
};
/**
* Creates a new analytics event with the given name.
* @param name {String} The name of the event.
* @returns {AnalyticsEvent} The [AnalyticsEvent]{@link AnalyticsEvent} instance that was logged.
*/
this.logNamedEvent = function (name) {
var event = new AnalyticsEvent(name);
this.logEvent(event);
return event;
};
/**
* Writes out an analytics event. It will implicitly call startSession(),
* which will add a new event to the list of events for Oracle Mobile Cloud Service to consume
* @param event {AnalyticsEvent} The event to log.
* @example event: "GettingStartedJSEvent"
* @returns {AnalyticsEvent} The [AnalyticsEvent]{@link AnalyticsEvent} instance that was logged.
*/
this.logEvent = function (event) {
if (_events.length === 0) {
_events[0] = this._createContextEvent();
}
this.startSession();
_events[_events.length] = event;
event.sessionID = _sessionId;
return event;
};
function locationEnabled(){
if(backend._config.analytics && typeof backend._config.analytics.location !== 'undefined'){
return backend._config.analytics.location;
} else {
return true;
}
}
/**
* Uploads all events to the service if the device is online or caches them locally until the device goes online, at
* which point they will be uploaded. If a session is in progress it will end.
* @param [successCallback] {Analytics~successCallback} Callback invoked on success (deprecated use promises instead).
* @param [errorCallback] {Analytics~errorCallback} Callback invoked on error (deprecated use promises instead).
* @return {Promise.<Object|NetworkResponse>}
*/
this.flush = function (successCallback, errorCallback) {
for (var i = 0; i < _events.length; i++) {
if (locationEnabled() && _events[i].name == "context") {
var gpsLocation = platform.getGPSLocation();
if (gpsLocation != null && gpsLocation.latitude != null) {
_events[i].properties.latitude = gpsLocation.latitude;
}
if (gpsLocation != null && gpsLocation.longitude != null) {
_events[i].properties.longitude = gpsLocation.longitude;
}
}
}
var eventsString = JSON.stringify(_events);
var headers = backend.getHttpHeaders(utils.MODULE_NAMES.MCS_ANALYTICS);
headers[utils.HEADERS.CONTENT_TYPE] = utils.ACCEPT_TYPES.APPLICATION_JSON;
return platform.invokeService({
method: utils.HTTP_METHODS.POST,
url: backend.getPlatformUrl("analytics/events"),
headers: headers,
data: eventsString
}).then(invokeServiceSuccess, invokeServiceError);
function invokeServiceSuccess() {
logger.verbose('Analytics events flushed.');
_events = [];
if (successCallback) {
successCallback();
}
}
function invokeServiceError(response) {
logger.error('Failed to flush analytics events.');
if (errorCallback) {
errorCallback(response.statusCode, response.data);
} else {
return Promise.reject(response);
}
}
};
this._createContextEvent = function () {
var contextEvent = new AnalyticsEvent("context");
contextEvent.type = "system";
contextEvent.properties.timezone = "" + new Date().getTimezoneOffset() * 60;
var deviceInformation = platform.getDeviceInformation();
contextEvent.properties.model = deviceInformation.model;
contextEvent.properties.manufacturer = deviceInformation.manufacturer;
contextEvent.properties.osName = deviceInformation.osName;
contextEvent.properties.osVersion = deviceInformation.osVersion;
contextEvent.properties.osBuild = deviceInformation.osBuild;
contextEvent.properties.carrier = deviceInformation.carrier;
return contextEvent;
};
}