com.eg.agent.android.analytics.BaseController Maven / Gradle / Ivy
The newest version!
package com.eg.agent.android.analytics;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.json.JSONException;
import org.json.JSONObject;
import com.eg.agent.android.gestures.GestureReporter;
import com.eg.agent.android.harvest.DataReaper;
import com.eg.agent.android.harvest.HttpData;
import com.eg.agent.android.harvest.ReapData;
import com.eg.agent.android.harvest.Reaper;
import com.eg.agent.android.harvest.ReaperAdapter;
import com.eg.agent.android.harvest.ReaperLifecycle;
import com.eg.agent.android.logging.EGAgentLog;
import com.eg.agent.android.logging.EGAgentLogManager;
import com.eg.agent.android.BaseAndroidAgent;
import com.eg.agent.android.DeviceData;
import com.eg.agent.android.EGAgentConfig;
import com.eg.agent.android.Features;
import com.eg.agent.android.Queue;
import com.eg.agent.android.trace.ActivityTracer;
import com.eg.agent.android.trace.TracerLifecycle;
import com.eg.agent.android.trace.TracerMachine;
public class BaseController extends ReaperAdapter implements Controller {
private static final String EG_PREFIX = "eg.";
private static final String EGURKHA_PREFIX = "eGurkha";
private static final AtomicBoolean initialized = new AtomicBoolean(false);
private static final BaseController instance = new BaseController();
static final EGAgentLog log = EGAgentLogManager.getAgentLog();
private static final List reservedNames = new ArrayList();
private EGAgentConfig agentConfiguration;
private BaseAndroidAgent agentImpl;
private BaseEventManager eventManager = new BaseEventManager();
private AtomicBoolean isEnabled;
private InteractionCompleteListener listener = new InteractionCompleteListener();
private Set systemAttributes = Collections.synchronizedSet(new HashSet());
private Set userAttributes = Collections.synchronizedSet(new HashSet());
class InteractionCompleteListener implements TracerLifecycle {
InteractionCompleteListener() {
}
public void onEnterMethod() {
}
public void onExitMethod() {
}
public void onTraceStart(ActivityTracer activityTrace) {
}
public void onTraceComplete(ActivityTracer activityTrace) {
BaseController.log.verbose("BaseController.InteractionCompleteListener.onTraceComplete invoke.");
BaseController.getInstance().addEvent(createTraceEvent(activityTrace));
}
private Event createTraceEvent(ActivityTracer activityTrace) {
float durationInSec = activityTrace.rootTrace.getDurationAsSeconds();
Set attrs = new HashSet();
attrs.add(new Attributes(Attributes.INTERACTION_DURATION_ATTRIBUTE, durationInSec));
return EventsFactory.createEvent(activityTrace.rootTrace.displayName, EventCategory.Interaction, Attributes.EVENT_TYPE_ATTRIBUTE_MOBILE, attrs);
}
@Override
public void onTraceRename(ActivityTracer var1) {
// TODO Auto-generated method stub
}
}
public static void initialize(EGAgentConfig agentConfiguration, BaseAndroidAgent agentImpl) {
log.debug("BaseController.initialize.::initialized::"+initialized.get());
if (initialized.compareAndSet(false, true)) {
instance.clear();
reservedNames.add(Attributes.EVENT_TYPE_ATTRIBUTE);
reservedNames.add(Attributes.TYPE_ATTRIBUTE);
reservedNames.add(Attributes.EVENT_TIMESTAMP_ATTRIBUTE);
reservedNames.add(Attributes.EVENT_CATEGORY_ATTRIBUTE);
reservedNames.add(Attributes.ACCOUNT_ID_ATTRIBUTE);
reservedNames.add(Attributes.APP_ID_ATTRIBUTE);
reservedNames.add(Attributes.APP_NAME_ATTRIBUTE);
reservedNames.add(Attributes.UUID_ATTRIBUTE);
// reservedNames.add(Attributes.SESSION_ID_ATTRIBUTE);
reservedNames.add(Attributes.OS_NAME_ATTRIBUTE);
reservedNames.add(Attributes.OS_VERSION_ATTRIBUTE);
reservedNames.add(Attributes.OS_MAJOR_VERSION_ATTRIBUTE);
reservedNames.add(Attributes.DEVICE_MANUFACTURER_ATTRIBUTE);
reservedNames.add(Attributes.DEVICE_MODEL_ATTRIBUTE);
reservedNames.add(Attributes.MEM_USAGE_MB_ATTRIBUTE);
reservedNames.add(Attributes.CARRIER_ATTRIBUTE);
reservedNames.add(Attributes.EG_VERSION_ATTRIBUTE);
reservedNames.add(Attributes.INTERACTION_DURATION_ATTRIBUTE);
reservedNames.add(Attributes.APP_INSTALL_ATTRIBUTE);
reservedNames.add(Attributes.APP_UPGRADE_ATTRIBUTE);
reservedNames.add(Attributes.APPLICATION_PLATFORM_ATTRIBUTE);
reservedNames.add(Attributes.APPLICATION_PLATFORM_VERSION_ATTRIBUTE);
reservedNames.add("osBuild");
reservedNames.add("runTime");
reservedNames.add("architecture");
reservedNames.add("appBuild");
instance.reinitialize(agentConfiguration, agentImpl);
TracerMachine.addTraceListener(instance.listener);
DataReaper.addHarvestListener((ReaperLifecycle)instance);
//log.info("Analytics Controller started.");
return;
}
log.verbose("BaseController has already been initialized. Bypassing..");
}
public static void shutdown() {
TracerMachine.removeTraceListener(instance.listener);
initialized.compareAndSet(true, false);
instance.getEventManager().shutdown();
}
private BaseController() {
this.isEnabled = new AtomicBoolean(false);
}
void reinitialize(EGAgentConfig agentConfiguration, BaseAndroidAgent agentImpl) {
String osMajorVersion;
this.agentImpl = agentImpl;
this.agentConfiguration = agentConfiguration;
this.eventManager.initialize();
this.isEnabled.set(agentConfiguration.getEnableAnalyticsEvents());
loadPersistentAttributes();
DeviceData deviceInformation = agentImpl.getDeviceInformation();
String osVersion = deviceInformation.getOsVersion().replace(" ", "");
String[] osMajorVersionArr = osVersion.split("[.:-]");
if (osMajorVersionArr.length > 0) {
osMajorVersion = osMajorVersionArr[0];
} else {
osMajorVersion = osVersion;
}
this.systemAttributes.add(new Attributes(Attributes.OS_NAME_ATTRIBUTE, deviceInformation.getOsName()));
this.systemAttributes.add(new Attributes(Attributes.OS_VERSION_ATTRIBUTE, osVersion));
this.systemAttributes.add(new Attributes(Attributes.OS_MAJOR_VERSION_ATTRIBUTE, osMajorVersion));
this.systemAttributes.add(new Attributes(Attributes.DEVICE_MANUFACTURER_ATTRIBUTE, deviceInformation.getManufacturer()));
this.systemAttributes.add(new Attributes(Attributes.DEVICE_MODEL_ATTRIBUTE, deviceInformation.getModel()));
this.systemAttributes.add(new Attributes(Attributes.UUID_ATTRIBUTE, deviceInformation.getDeviceId()));
this.systemAttributes.add(new Attributes(Attributes.CARRIER_ATTRIBUTE, agentImpl.getNetworkCarrier()));
this.systemAttributes.add(new Attributes(Attributes.EG_VERSION_ATTRIBUTE, deviceInformation.getAgentVersion()));
// this.systemAttributes.add(new Attributes(Attributes.SESSION_ID_ATTRIBUTE, agentConfiguration.getSessionID()));
this.systemAttributes.add(new Attributes(Attributes.APPLICATION_PLATFORM_ATTRIBUTE, agentConfiguration.getApplicationPlatform().toString()));
this.systemAttributes.add(new Attributes(Attributes.APPLICATION_PLATFORM_VERSION_ATTRIBUTE, agentConfiguration.getApplicationPlatformVersion()));
}
public Attributes getAttribute(String name) {
//log.verbose("BaseController.getAttribute - retrieving " + name);
Attributes attribute = getUserAttribute(name);
if (attribute == null) {
return getSystemAttribute(name);
}
return attribute;
}
public Set getSystemAttributes() {
Set attrs = new HashSet(this.systemAttributes.size());
for (Attributes attr : this.systemAttributes) {
attrs.add(new Attributes(attr));
}
return Collections.unmodifiableSet(attrs);
}
public Set getUserAttributes() {
// Set attrs = new HashSet(this.userAttributes.size());
// for (Attributes attr : this.userAttributes) {
// attrs.add(new Attributes(attr));
// }
log.debug("BaseController::getUserAttributes:::userAttributes:::"+userAttributes);
return Collections.unmodifiableSet(this.userAttributes);
}
public Set getSessionAttributes() {
Set attrs = new HashSet();
attrs.addAll(getSystemAttributes());
attrs.addAll(getUserAttributes());
return Collections.unmodifiableSet(attrs);
}
public int getSystemAttributeCount() {
return this.systemAttributes.size();
}
public int getUserAttributeCount() {
return this.userAttributes.size();
}
public int getSessionAttributeCount() {
return this.systemAttributes.size() + this.userAttributes.size();
}
public boolean setAttribute(String name, String value) {
log.verbose("BaseController.setAttribute - " + name + ": " + value);
return setAttribute(name, value, true);
}
public boolean setAttribute(String name, String value, boolean persistent) {
log.verbose("BaseController.setAttribute - " + name + ": " + value + (persistent ? " (persistent)" : " (transient)"));
if (!isInitializedAndEnabled() || !isAttributeNameValid(name) || !isStringValueValid(name, value)) {
return false;
}
Attributes attribute = getAttribute(name);
boolean stored;
if (attribute != null) {
attribute.setStringValue(value);
attribute.setPersistent(persistent);
if (attribute.isPersistent()) {
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
} else {
this.agentConfiguration.getAnalyticAttributeStore().delete(attribute);
}
} else if (this.userAttributes.size() < 64) {
attribute = new Attributes(name, value, persistent);
this.userAttributes.add(attribute);
if (attribute.isPersistent()) {
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
}
} else {
//log.warning("Attribute limit exceeded: at most 64 are allowed.");
//log.warning("Currently defined attributes:");
for (Attributes attr : this.userAttributes) {
log.warning("\t" + attr.getName() + ": " + attr.valueAsString());
}
}
return true;
}
public boolean setAttribute(String name, float value) {
log.verbose("BaseController.setAttribute - " + name + ": " + value);
return setAttribute(name, value, true);
}
public boolean setAttribute(String name, float value, boolean persistent) {
log.verbose("BaseController.setAttribute - " + name + ": " + value + (persistent ? " (persistent)" : " (transient)"));
if (!isInitializedAndEnabled() || !isAttributeNameValid(name)) {
return false;
}
Attributes attribute = getAttribute(name);
boolean stored;
if (attribute != null) {
attribute.setFloatValue(value);
attribute.setPersistent(persistent);
if (attribute.isPersistent()) {
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
} else {
this.agentConfiguration.getAnalyticAttributeStore().delete(attribute);
}
} else if (this.userAttributes.size() < 64) {
attribute = new Attributes(name, value, persistent);
this.userAttributes.add(attribute);
if (attribute.isPersistent()) {
this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
}
} else {
//log.warning("Attribute limit exceeded: at most 64 are allowed.");
//log.warning("Currently defined attributes:");
for (Attributes attr : this.userAttributes) {
//log.warning("\t" + attr.getName() + ": " + attr.valueAsString());
}
}
return true;
}
public boolean setAttribute(String name, boolean value) {
log.verbose("BaseController.setAttribute - " + name + ": " + value);
return setAttribute(name, value, true);
}
public boolean setAttribute(String name, boolean value, boolean persistent) {
log.verbose("BaseController.setAttribute - " + name + ": " + value + (persistent ? " (persistent)" : " (transient)"));
if (!isInitializedAndEnabled() || !isAttributeNameValid(name)) {
return false;
}
Attributes attribute = getAttribute(name);
boolean stored;
if (attribute != null) {
attribute.setBooleanValue(value);
attribute.setPersistent(persistent);
if (attribute.isPersistent()) {
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
} else {
this.agentConfiguration.getAnalyticAttributeStore().delete(attribute);
}
} else if (this.userAttributes.size() < 64) {
attribute = new Attributes(name, value, persistent);
this.userAttributes.add(attribute);
if (attribute.isPersistent()) {
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
}
} else {
//log.warning("Attribute limit exceeded: at most 64 are allowed.");
//log.warning("Currently defined attributes:");
for (Attributes attr : this.userAttributes) {
// log.warning("\t" + attr.getName() + ": " + attr.valueAsString());
}
}
return true;
}
public boolean setAttribute(String name, double value) {
log.debug("BaseController.setAttribute - " + name + ": " + value);
return setAttribute(name, value, true);
}
public boolean setAttribute(String name, double value, boolean persistent) {
log.debug("BaseController.setAttribute - " + name + ": " + value + (persistent ? " (persistent)" : " (transient)"));
if (!isInitializedAndEnabled())
return false;
if (!isAttributeNameValid(name))
return false;
Attributes attribute = getAttribute(name);
log.debug("BaseController.setAttribute::attribute::"+attribute);
if (attribute == null) {
attribute = new Attributes(name, value, persistent);
this.userAttributes.add(attribute);
} else {
attribute.setDoubleValue(value);
attribute.setPersistent(persistent);
}
log.debug("BaseController.setAttribute::userAttributes::"+userAttributes);
if (attribute.isPersistent()) {
if (!this.agentConfiguration.getAnalyticAttributeStore().store(attribute)) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return false;
}
} else {
this.agentConfiguration.getAnalyticAttributeStore().delete(attribute);
}
return true;
}
public boolean incrementAttribute(String name, double value) {
log.debug("BaseController.incrementAttribute - " + name + ": " + value);
return incrementAttribute(name, value, true);
}
public boolean incrementAttribute(String name, double value, boolean persistent) {
log.debug("BaseController.incrementAttribute - " + name + ": " + value + (persistent ? " (persistent)" : " (transient)"));
if (!isInitializedAndEnabled())
return false;
if (!isAttributeNameValid(name))
return false;
Attributes attribute = getAttribute(name);
if (attribute != null && attribute.isDoubleAttribute()) {
attribute.setDoubleValue(attribute.getDoubleValue() + value);
attribute.setPersistent(persistent);
if (attribute.isPersistent() &&
!this.agentConfiguration.getAnalyticAttributeStore().store(attribute)) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return false;
}
} else {
if (attribute == null) {
addNewUserAttribute(new Attributes(name, value, persistent));
// this.userAttributes.add(attribute);
}
log.warning("Cannot increment attribute " + name + ": the attribute is already defined as a non-float value.");
return false;
}
return true;
}
private boolean addNewUserAttribute(Attributes attribute) {
if (this.userAttributes.size() < 128) {
this.userAttributes.add(attribute);
if (attribute.isPersistent() &&
!this.agentConfiguration.getAnalyticAttributeStore().store(attribute)) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return false;
}
} else {
log.warning("Attribute limit exceeded: at most 128 are allowed.");
log.debug("Currently defined attributes:");
for (Attributes attr : this.userAttributes)
log.debug("\t" + attr.getName() + ": " + attr.valueAsString());
}
return true;
}
public boolean addAttributeUnchecked(Attributes attribute, boolean persistent) {
String name = attribute.getName();
//log.verbose("BaseController.setAttributeUnchecked - " + name + ": " + attribute.valueAsString() + (persistent ? " (persistent)" : " (transient)"));
if (!initialized.get()) {
log.warning("Analytics controller is not initialized!");
return false;
} else if (!this.isEnabled.get()) {
log.warning("Analytics controller is not enabled!");
return false;
} else if (!isNameValid(name)) {
return false;
} else {
Attributes foundAttribute = getAttribute(attribute.getName());
boolean stored;
if (foundAttribute == null) {
this.userAttributes.add(attribute);
if (attribute.isPersistent()) {
this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
}
}
switch (attribute.getAttributeDataType()) {
case STRING:
foundAttribute.setStringValue(attribute.getStringValue());
break;
case FLOAT:
foundAttribute.setFloatValue(attribute.getFloatValue());
break;
case BOOLEAN:
foundAttribute.setBooleanValue(attribute.getBooleanValue());
break;
}
foundAttribute.setPersistent(persistent);
if (foundAttribute.isPersistent()) {
stored = this.agentConfiguration.getAnalyticAttributeStore().store(foundAttribute);
if (!stored) {
log.error("Failed to store attribute " + foundAttribute + " to attribute store.");
return stored;
}
}
this.agentConfiguration.getAnalyticAttributeStore().delete(foundAttribute);
return true;
}
}
public boolean incrementAttribute(String name, float value) {
//log.verbose("BaseController.incrementAttribute - " + name + ": " + value);
return incrementAttribute(name, value, true);
}
public boolean incrementAttribute(String name, float value, boolean persistent) {
//log.verbose("BaseController.incrementAttribute - " + name + ": " + value + (persistent ? " (persistent)" : " (transient)"));
if (!isInitializedAndEnabled() || !isAttributeNameValid(name)) {
return false;
}
Attributes attribute = getAttribute(name);
boolean stored;
if (attribute != null && attribute.isFloatAttribute()) {
attribute.setFloatValue(attribute.getFloatValue() + value);
attribute.setPersistent(persistent);
if (attribute.isPersistent()) {
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
}
} else if (attribute != null) {
log.warning("Cannot increment attribute " + name + ": the attribute is already defined as a non-float value.");
return false;
} else if (this.userAttributes.size() < 64) {
attribute = new Attributes(name, value, persistent);
this.userAttributes.add(attribute);
if (attribute.isPersistent()) {
this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
stored = this.agentConfiguration.getAnalyticAttributeStore().store(attribute);
if (!stored) {
log.error("Failed to store attribute " + attribute + " to attribute store.");
return stored;
}
}
this.agentConfiguration.getAnalyticAttributeStore().delete(attribute);
}
return true;
}
public boolean removeAttribute(String name) {
//log.verbose("BaseController.removeAttribute - " + name);
if (!isInitializedAndEnabled()) {
return false;
}
Attributes attribute = getAttribute(name);
if (attribute != null) {
this.userAttributes.remove(attribute);
if (attribute.isPersistent()) {
this.agentConfiguration.getAnalyticAttributeStore().delete(attribute);
}
}
return true;
}
public boolean removeAllAttributes() {
//log.verbose("BaseController.removeAttributes - ");
if (isInitializedAndEnabled()) {
this.agentConfiguration.getAnalyticAttributeStore().clear();
this.userAttributes.clear();
}
return false;
}
public boolean addEvent(String name, Set eventAttributes) {
return addEvent(name, EventCategory.Custom, Attributes.EVENT_TYPE_ATTRIBUTE_MOBILE, eventAttributes);
}
public boolean addEvent(String name, EventCategory eventCategory, String eventType, Set eventAttributes) {
//log.verbose("BaseController.addEvent - " + name + ": category=" + eventCategory + ", eventType: " + eventType + ", eventAttributes:" + eventAttributes);
if (!isInitializedAndEnabled()) {
return false;
}
Set validatedAttributes = new HashSet();
for (Attributes attribute : eventAttributes) {
if (isAttributeNameValid(attribute.getName())) {
validatedAttributes.add(attribute);
}
}
return addEvent(EventsFactory.createEvent(name, eventCategory, eventType, validatedAttributes));
}
public boolean addEvent(Event event) {
log.debug("BaseController::addEvent:::isInitializedAndEnabled:::"+isInitializedAndEnabled());
log.debug("BaseController::addEvent:::event:::"+event);
if (!isInitializedAndEnabled() || event == null) {
return false;
}
Set sessionAttributes = new HashSet();
long sessionDuration = this.agentImpl.getSessionDurationMillis();
if (0 == sessionDuration) {
log.error("Harvest instance is not running! Session duration will be invalid");
} else {
sessionAttributes.add(new Attributes("timeSinceLoad", (((float) sessionDuration) / 1000.0f)+" (in Secs)"));
event.addAttributes(sessionAttributes);
}
log.debug("BaseController::addEvent:::eventManager:::"+eventManager);
// Queue.queue(GestureReporter.getJSONObject(event.getAttributeSet()));
// return true;
return this.eventManager.addEvent(event);
}
public int getMaxEventPoolSize() {
return this.eventManager.getMaxEventPoolSize();
}
public void setMaxEventPoolSize(int maxSize) {
this.eventManager.setMaxEventPoolSize(maxSize);
}
public void setMaxEventBufferTime(int maxBufferTimeInSec) {
this.eventManager.setMaxEventBufferTime(maxBufferTimeInSec);
}
public int getMaxEventBufferTime() {
return this.eventManager.getMaxEventBufferTime();
}
public EventManager getEventManager() {
return this.eventManager;
}
public static BaseController getInstance() {
return instance;
}
public boolean internalRecordEvent(String name, EventCategory eventCategory, String eventType, Map eventAttributes)
{
// log.verbose("BaseController.recordEvent - " + name + ": " + eventAttributes.size() + " attributes");
log.info("internalRecordEvent - " + name + ": " + eventAttributes+", Category: "+eventCategory+", type:"+eventType);
log.debug("isInitializedAndEnabled:::"+isInitializedAndEnabled());
log.debug("this.eventManager.isEventTypeValid("+eventType+") :: "+this.eventManager.isEventTypeValid(eventType));
if (!isInitializedAndEnabled()) {
return false;
}
if (!this.eventManager.isEventTypeValid(eventType)) {
return false;
}
Set attributes = new HashSet();
try
{
for (String key : eventAttributes.keySet())
{
Object value = eventAttributes.get(key);
Attributes attr = createAttribute(key, value);
if (attr == null) {
continue;
}
attributes.add(attr);
}
}
catch (Exception e)
{
log.error(String.format("Error occurred while recording event [%s]: ", new Object[] { name }), e);
}
log.debug("attributes.isEmpty() "+attributes.isEmpty());
if(attributes.isEmpty()) {
return false;
}
return addEvent(name, eventCategory, eventType, attributes, false);
}
void loadPersistentAttributes() {
//log.verbose("BaseController.loadPersistentAttributes - loading userAttributes from the attribute store...");
List storedAttrs = this.agentConfiguration.getAnalyticAttributeStore() == null? new ArrayList(): this.agentConfiguration.getAnalyticAttributeStore().fetchAll();
//log.verbose("BaseController.loadPersistentAttributes - found " + storedAttrs.size() + " userAttributes in the attribute store...");
for (Attributes attr : storedAttrs) {
this.userAttributes.add(attr);
}
}
private Attributes getSystemAttribute(String name) {
for (Attributes nextAttribute : this.systemAttributes) {
if (nextAttribute.getName().equals(name)) {
return nextAttribute;
}
}
return null;
}
private Attributes getUserAttribute(String name) {
for (Attributes nextAttribute : this.userAttributes) {
if (nextAttribute.getName().equals(name)) {
return nextAttribute;
}
}
return null;
}
private void clear() {
//log.verbose("BaseController.clear - clearing out attributes and events");
this.systemAttributes.clear();
this.userAttributes.clear();
this.eventManager.empty();
}
private boolean isAttributeNameValid(String name) {
boolean valid = isNameValid(name);
if (valid) {
valid = !isNameReserved(name);
if (!valid) {
log.error("Attribute name " + name + " is reserved for internal use and will be ignored.");
}
}
return valid;
}
private boolean isNameValid(String name) {
boolean valid = (name == null || name.equals("") || name.length() >= 256) ? false : true;
if (!valid) {
log.error("Attribute name " + name + " is null, empty, or exceeds the maximum length of " + 256 + " characters.");
}
return valid;
}
private boolean isStringValueValid(String name, String value) {
boolean valid = (value == null || value.equals("") || value.getBytes().length >= 4096) ? false : true;
if (!valid) {
log.error("Attribute value for name " + name + " is null, empty, or exceeds the maximum length of " + 4096 + " bytes.");
}
return valid;
}
private boolean isNameReserved(String name) {
boolean isReserved = reservedNames.contains(name);
if (isReserved) {
//log.verbose("Name " + name + " is in the reserved names list.");
return isReserved;
}
if (isReserved || name.startsWith(EG_PREFIX)) {
isReserved = true;
} else {
isReserved = false;
}
if (isReserved) {
return isReserved;
}
if (isReserved || name.startsWith(EGURKHA_PREFIX)) {
isReserved = true;
} else {
isReserved = false;
}
if (isReserved) {
//log.verbose("Name " + name + " starts with reserved prefix " + EG_PREFIX);
}
return isReserved;
}
public boolean recordEvent(String name, Map eventAttributes) {
// log.verbose("BaseController.recordEvent - " + name + ": " + eventAttributes.size() + " attributes");
log.info("recordEvent - " + name + ": " + eventAttributes);
if (!isInitializedAndEnabled()) {
return false;
}
Set attributes = new HashSet();
try {
for (String key : eventAttributes.keySet()) {
Object value = eventAttributes.get(key);
try {
if (value instanceof String) {
attributes.add(new Attributes(key, String.valueOf(value)));
} else if (value instanceof Float) {
attributes.add(new Attributes(key, Float.valueOf(((Float) value).floatValue()).floatValue()));
} else if (value instanceof Double) {
attributes.add(new Attributes(key, Float.valueOf(((Double) value).floatValue()).floatValue()));
} else if (value instanceof Integer) {
attributes.add(new Attributes(key, Float.valueOf((float) ((Integer) value).intValue()).floatValue()));
} else if (value instanceof Short) {
attributes.add(new Attributes(key, Float.valueOf((float) ((Short) value).shortValue()).floatValue()));
} else if (value instanceof Long) {
attributes.add(new Attributes(key, Float.valueOf((float) ((Long) value).longValue()).floatValue()));
} else if (value instanceof BigDecimal) {
attributes.add(new Attributes(key, Float.valueOf(((BigDecimal) value).floatValue()).floatValue()));
} else if (value instanceof BigInteger) {
attributes.add(new Attributes(key, Float.valueOf(((BigInteger) value).floatValue()).floatValue()));
} else if (value instanceof Boolean) {
attributes.add(new Attributes(key, Boolean.valueOf(((Boolean) value).booleanValue()).booleanValue()));
} else {
//log.error("Unsupported event attribute type for key [" + key + "]: " + value.getClass().getName());
return false;
}
} catch (ClassCastException e) {
log.error(String.format("Error casting attribute [%s] to String or Float: ", new Object[]{key}), e);
}
}
} catch (Exception e2) {
log.error(String.format("Error occurred while recording event [%s]: ", new Object[]{name}), e2);
}
return addEvent(name, EventCategory.Custom, Attributes.EVENT_TYPE_ATTRIBUTE_MOBILE, attributes);
}
public boolean recordCustomEvent(String eventType, Map eventAttributes) {
try {
log.debug("BaseController.recordCustomEvent - " + eventType + ": " + eventAttributes.size() + " attributes");
if (!isInitializedAndEnabled())
return false;
if (this.eventManager.isEventTypeReserved(eventType) || !this.eventManager.isEventTypeValid(eventType))
return false;
String eventName = eventType;
Set attributes = new HashSet<>();
for (String key : eventAttributes.keySet()) {
Object value = eventAttributes.get(key);
Attributes attr = createAttribute(key, value);
if (attr != null) {
if (attr.getName().equals("name")) {
String name = attr.getStringValue();
if (name != null && !name.isEmpty())
eventName = attr.getStringValue();
}
attributes.add(attr);
}
}
return addEvent(eventName, EventCategory.Custom, eventType, attributes);
} catch (Exception e) {
log.error(String.format("Error occurred while recording custom event [%s]: ", new Object[] { eventType }), e);
return false;
}
}
public boolean recordBreadcrumb(String name, Map eventAttributes) {
try {
if (!isInitializedAndEnabled())
return false;
Set attributes = new HashSet<>();
for (String key : eventAttributes.keySet()) {
Object value = eventAttributes.get(key);
Attributes attr = createAttribute(key, value);
if (attr != null)
attributes.add(attr);
}
return addEvent(name, EventCategory.Breadcrumb, "MobileBreadcrumb", attributes);
} catch (Exception e) {
log.error(String.format("Error occurred while recording Breadcrumb event [%s]: ", new Object[] { name }), e);
return false;
}
}
// public boolean internalRecordEvent(String name, EventCategory eventCategory, String eventType, Map eventAttributes) {
// try {
// log.debug("BaseController.recordEvent - " + name + ": " + eventAttributes.size() + " attributes");
// if (!isInitializedAndEnabled())
// return false;
// if (!this.eventManager.isEventTypeValid(eventType))
// return false;
// Set attributes = new HashSet<>();
// for (String key : eventAttributes.keySet()) {
// Object value = eventAttributes.get(key);
// Attributes attr = createAttribute(key, value);
// if (attr != null)
// attributes.add(attr);
// }
// return addEvent(name, eventCategory, eventType, attributes, false);
// } catch (Exception e) {
// log.error(String.format("Error occurred while recording event [%s]: ", new Object[] { name }), e);
// return false;
// }
// }
public boolean recordEvent(String name, EventCategory eventCategory, String eventType, Map eventAttributes) {
try {
log.debug("BaseController.recordEvent - " + name + ": " + eventAttributes.size() + " attributes");
if (!isInitializedAndEnabled())
return false;
if (!this.eventManager.isEventTypeValid(eventType))
return false;
Set attributes = new HashSet<>();
for (String key : eventAttributes.keySet()) {
Object value = eventAttributes.get(key);
Attributes attr = createAttribute(key, value);
if (attr != null)
attributes.add(attr);
}
return addEvent(name, eventCategory, eventType, attributes);
} catch (Exception e) {
log.error(String.format("Error occurred while recording event [%s]: ", new Object[] { name }), e);
return false;
}
}
void createHttpErrorEvent(HttpData txn) {
if (isInitializedAndEnabled())
NetworkEventController.createHttpErrorEvent(txn);
}
void createNetworkFailureEvent(HttpData txn) {
if (isInitializedAndEnabled())
NetworkEventController.createNetworkFailureEvent(txn);
}
void createNetworkRequestEvent(HttpData txn) {
if (isInitializedAndEnabled())
NetworkEventController.createNetworkRequestEvent(txn);
}
public void createNetworkRequestEvents(HttpData txn) {
if (isInitializedAndEnabled())
if (isHttpError(txn)) {
NetworkEventController.createHttpErrorEvent(txn);
} else if (isNetworkFailure(txn)) {
NetworkEventController.createNetworkFailureEvent(txn);
} else if (isSuccessfulRequest(txn)) {
NetworkEventController.createNetworkRequestEvent(txn);
}
}
private boolean isNetworkFailure(HttpData txn) {
return (txn.getErrorCode() != 0);
}
private boolean isHttpError(HttpData txn) {
return (txn.getStatusCode() >= 400L);
}
private boolean isSuccessfulRequest(HttpData txn) {
return (txn.getStatusCode() > 0 && txn.getStatusCode() < 400);
}
private boolean isInitializedAndEnabled() {
if (!initialized.get()) {
log.warning("Analytics controller is not initialized!");
return false;
} else if (this.isEnabled.get()) {
return true;
} else {
log.warning("Analytics controller is not enabled!");
return false;
}
}
Attributes createAttribute(String key, Object value)
{
if(value == null) {
return null;
}
try
{
if ((value instanceof String)) {
return new Attributes(key, String.valueOf(value));
}
if ((value instanceof Float)) {
return new Attributes(key, Float.valueOf(((Float)value).floatValue()).floatValue());
}
if ((value instanceof Double)) {
return new Attributes(key, Float.valueOf(((Double)value).floatValue()).floatValue());
}
if ((value instanceof Integer)) {
return new Attributes(key, Float.valueOf(((Integer)value).intValue()).floatValue());
}
if ((value instanceof Short)) {
return new Attributes(key, Float.valueOf(((Short)value).shortValue()).floatValue());
}
if ((value instanceof Long)) {
return new Attributes(key, Float.valueOf((float)((Long)value).longValue()).floatValue());
}
if ((value instanceof BigDecimal)) {
return new Attributes(key, Float.valueOf(((BigDecimal)value).floatValue()).floatValue());
}
if ((value instanceof BigInteger)) {
return new Attributes(key, Float.valueOf(((BigInteger)value).floatValue()).floatValue());
}
if ((value instanceof Boolean)) {
return new Attributes(key, Boolean.valueOf(((Boolean)value).booleanValue()).booleanValue());
}
if(value instanceof JSONObject) {
JSONObject gesture = (JSONObject) value;
try {
gesture.put( "orientation", GestureReporter.getOrientation());
} catch (JSONException e) {
log.error("Adding orientation:: "+e.getMessage());
}
return new Attributes(key, gesture.toString());
}
log.error("Unsupported event attribute type for key [" + key + "]: " + value.getClass().getName());
return null;
}
catch (ClassCastException e)
{
log.error(String.format("Error casting attribute [%s] to String or Float: ", new Object[] { key }), e);
}
return null;
}
boolean addEvent(String name, EventCategory eventCategory, String eventType, Set eventAttributes, boolean validate)
{
// log.verbose("BaseController.addEvent - " + name + ": category=" + eventCategory + ", eventType: " + eventType + ", eventAttributes:" + eventAttributes);
log.verbose("BaseController::addEvent - " + name + ": category=" + eventCategory + ", eventType: " + eventType + ", eventAttributes:" + eventAttributes);
log.debug("BaseController::addEvent:::isInitializedAndEnabled:::"+isInitializedAndEnabled());
if (!isInitializedAndEnabled()) {
return false;
}
Set validatedAttributes = new HashSet();
log.debug("BaseController::addEvent:::validate:::"+validate);
if (validate) {
for (Attributes attribute : eventAttributes) {
if (isAttributeNameValid(attribute.getName())) {
validatedAttributes.add(attribute);
}
}
} else {
for (Attributes attribute : eventAttributes) {
if (isNameValid(attribute.getName())) {
validatedAttributes.add(attribute);
}
}
}
Event event = EventsFactory.createEvent(name, eventCategory, eventType, validatedAttributes);
log.debug("BaseController::addEvent:::event:::"+event);
return addEvent(event);
}
public void onHarvest() {
ReapData harvestData = DataReaper.getInstance().getHarvestData();
log.debug("BaseController::onHarvest:::harvestData:::"+harvestData);
if (harvestData != null) {
log.debug("BaseController::onHarvest:::isEnabled.get():::"+this.isEnabled.get());
log.debug("BaseController::onHarvest:::Features.featureEnabled(Features.AnalyticsEvents):::"+Features.featureEnabled(Features.AnalyticsEvents));
harvestData.setAnalyticsEnabled(this.isEnabled.get());
if (this.isEnabled.get() && Features.featureEnabled(Features.AnalyticsEvents))
log.debug("BaseController::onHarvest:::eventManager.isTransmitRequired():::"+this.eventManager.isTransmitRequired());
Set sessionAttributes = new HashSet<>();
sessionAttributes.addAll(getSystemAttributes());
sessionAttributes.addAll(getUserAttributes());
// for(Object value :BaseAndroidAgent.getInstance().getUserdata().values()) {
// sessionAttributes.add(new Attributes("userData", value.toString()));
// }
if (this.eventManager.isTransmitRequired()) {
harvestData.setSessionAttributes(sessionAttributes);
Collection pendingEvents = this.eventManager.getQueuedEventsSnapshot();
if (pendingEvents.size() > 0) {
harvestData.getAnalyticsEvents().addAll(pendingEvents);
log.debug("EventManager: [" + pendingEvents.size() + "] events moved from buffer to HarvestData");
}
if (this.eventManager.getQueuedEvents().size() > 0)
log.error("EventManager: [" + this.eventManager.getQueuedEvents().size() + "] events remain in buffer after hand-off");
}
}
}
}