diff --git a/pom.xml b/pom.xml index 8507e33ad..34b50313c 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,12 @@ com.google.cloud google-cloud-pubsub + + com.brsanthu + google-analytics-java + 2.0.0 + + org.javalite activejdbc diff --git a/src/main/java/org/broadinstitute/dsm/DSMServer.java b/src/main/java/org/broadinstitute/dsm/DSMServer.java index 9d195128f..f403260d4 100644 --- a/src/main/java/org/broadinstitute/dsm/DSMServer.java +++ b/src/main/java/org/broadinstitute/dsm/DSMServer.java @@ -31,6 +31,8 @@ import org.broadinstitute.ddp.util.BasicTriggerListener; import org.broadinstitute.ddp.util.JsonTransformer; import org.broadinstitute.ddp.util.Utility; +import org.broadinstitute.dsm.analytics.GoogleAnalyticsMetrics; +import org.broadinstitute.dsm.analytics.GoogleAnalyticsMetricsTracker; import org.broadinstitute.dsm.careevolve.Provider; import org.broadinstitute.dsm.jetty.JettyConfig; import org.broadinstitute.dsm.jobs.*; @@ -167,12 +169,14 @@ protected void configureServer(@NonNull Config config) { logger.info("Using port {}", port); port(port); - registerAppEngineStartupCallback(bootTimeoutSeconds); + registerAppEngineStartupCallback(bootTimeoutSeconds, config); setupDB(config); // don't run superclass routing--it won't work with JettyConfig changes for capturing proper IP address in GAE setupCustomRouting(config); + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics("", GoogleAnalyticsMetrics.EVENT_CATEGORY_SERVER_START, + GoogleAnalyticsMetrics.EVENT_ACTION_SERVER_START, GoogleAnalyticsMetrics.EVENT_LABEL_SERVER_START, 1 ); List allowedOrigins = config.getStringList(ApplicationConfigConstants.CORS_ALLOWED_ORIGINS); enableCORS(StringUtils.join(allowedOrigins, ","), String.join(",", CORS_HTTP_METHODS), String.join(",", CORS_HTTP_HEADERS)); @@ -834,14 +838,25 @@ public static boolean isTest(@NonNull String shipperName) { return true; } - private static void registerAppEngineStartupCallback(long bootTimeoutSeconds) { + private static void registerAppEngineStartupCallback(long bootTimeoutSeconds, Config cfg) { + GoogleAnalyticsMetricsTracker.setConfig(cfg); // Block until isReady is available, with an optional timeout to prevent // instance for sitting around too long in a nonresponsive state. There is a // judgement call to be made here to allow for lengthy liquibase migrations during boot. logger.info("Will wait for at most {} seconds for boot before GAE termination", bootTimeoutSeconds); get("/_ah/start", new ReadinessRoute(bootTimeoutSeconds)); + + get(RoutePath.GAE.STOP_ENDPOINT, (request, response) -> { + logger.info("Received GAE stop request [{}]", RoutePath.GAE.STOP_ENDPOINT); + //flush out any pending GA events + GoogleAnalyticsMetricsTracker.getInstance().flushOutMetrics(); + + response.status(HttpStatus.SC_OK); + return ""; + }); } + private static class ReadinessRoute implements Route { private final long bootTimeoutSeconds; diff --git a/src/main/java/org/broadinstitute/dsm/analytics/GoogleAnalyticsMetrics.java b/src/main/java/org/broadinstitute/dsm/analytics/GoogleAnalyticsMetrics.java new file mode 100644 index 000000000..7fa466be6 --- /dev/null +++ b/src/main/java/org/broadinstitute/dsm/analytics/GoogleAnalyticsMetrics.java @@ -0,0 +1,29 @@ +package org.broadinstitute.dsm.analytics; + +public class GoogleAnalyticsMetrics { + +// public static final String EVENT_CATEGORY_USER_REGISTRATION = "user-registration"; +// public static final String EVENT_ACTION_USER_REGISTRATION = "register-user"; +// public static final String EVENT_LABEL_USER_REGISTRATION = "registration"; we may need it for FON + + public static final String EVENT_CATEGORY_USER_LOGIN = "user-login"; + public static final String EVENT_ACTION_USER_LOGIN = "user-logged-in"; + public static final String EVENT_LABEL_USER_LOGIN = "login"; //studyGuid appended + + public static final String EVENT_CATEGORY_PARTICIPANT_LIST = "participant-list"; + public static final String EVENT_ACTION_PARTICIPANT_LIST = "participant-list-load-time"; + public static final String EVENT_LABEL_PARTICIPANT_LIST = "participant-list-load-time";//studyGuid appended + + public static final String EVENT_CATEGORY_SERVER_START= "server-start"; + public static final String EVENT_ACTION_SERVER_START = "server-start"; + public static final String EVENT_LABEL_SERVER_START = "server-start"; + + public static final String EVENT_CATEGORY_PATCH_DATA = "patch-data"; + public static final String EVENT_ACTION_PATCH_DATA = "patch-data-answers"; + public static final String EVENT_LABEL_PATCH_DATA = "patch-answers"; //studyGuid & original page appended + + public static final String EVENT_CATEGORY_TISSUE_LIST = "tissue-list"; + public static final String EVENT_ACTION_TISSUE_LIST = "tissue-list-loaded"; + public static final String EVENT_LABEL_TISSUE_LIST = "tissue-list-loaded";//studyGuid appended + +} diff --git a/src/main/java/org/broadinstitute/dsm/analytics/GoogleAnalyticsMetricsTracker.java b/src/main/java/org/broadinstitute/dsm/analytics/GoogleAnalyticsMetricsTracker.java new file mode 100644 index 000000000..5be5e14a1 --- /dev/null +++ b/src/main/java/org/broadinstitute/dsm/analytics/GoogleAnalyticsMetricsTracker.java @@ -0,0 +1,98 @@ +package org.broadinstitute.dsm.analytics; + +import com.brsanthu.googleanalytics.GoogleAnalytics; +import com.brsanthu.googleanalytics.GoogleAnalyticsConfig; +import com.brsanthu.googleanalytics.request.EventHit; +import com.brsanthu.googleanalytics.request.GoogleAnalyticsResponse; +import com.typesafe.config.Config; +import lombok.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GoogleAnalyticsMetricsTracker { + private static final Logger logger = LoggerFactory.getLogger(GoogleAnalyticsMetricsTracker.class); + private static final String GA_TOKEN_PATH = "GoogleAnalytics.trackingId"; + private static GoogleAnalytics googleAnalyticsTrackers; + private static volatile GoogleAnalyticsMetricsTracker instance; + private static Object lockGA = new Object(); + private static Config CONFIG; + + private GoogleAnalyticsMetricsTracker() { + initStudyMetricTracker(); + } + + public static void setConfig(@NonNull Config config){ + CONFIG = config; + } + + public static GoogleAnalyticsMetricsTracker getInstance() { + if (instance == null) { + synchronized (lockGA) { + if (instance == null) { + instance = new GoogleAnalyticsMetricsTracker(); + } + } + } + return instance; + } + + private GoogleAnalytics getMetricTracker() { + if (googleAnalyticsTrackers == null) { + + initStudyMetricTracker(); + } + return googleAnalyticsTrackers; + } + + private synchronized void initStudyMetricTracker() { + GoogleAnalytics metricTracker = GoogleAnalytics.builder() + .withConfig(new GoogleAnalyticsConfig().setGatherStats(true).setUserAgent("Custom User Agent")) + .withTrackingId(getAnalyticsToken(CONFIG)) + .build(); + googleAnalyticsTrackers = metricTracker; + logger.info("Initialized GA Metrics Tracker for DSM "); + } + + + private void sendEventMetrics(EventHit eventHit) { + GoogleAnalytics metricTracker = getMetricTracker(); + if (metricTracker != null) { + GoogleAnalyticsResponse response = metricTracker.event().eventCategory(eventHit.eventCategory()) + .eventAction(eventHit.eventAction()) + .eventLabel(eventHit.eventLabel()) + .eventValue(eventHit.eventValue()) + .trackingId(getAnalyticsToken(CONFIG)) + .send(); + + logger.info(response.toString()); + logger.info(response.getStatusCode()+""); + logger.info(metricTracker.getStats().getEventHits()+""); + + } + } + + public void sendAnalyticsMetrics(String studyGuid, String category, String action, String label, int value) { + String gaEventLabel = String.join(":", label, + studyGuid); + EventHit eventHit = new EventHit(category, action, gaEventLabel, value); + logger.info(eventHit.toString()); + sendEventMetrics(eventHit); + + } + + public void flushOutMetrics() { + //lookup all Metrics Trackers and flush out any pending events + logger.info("Flushing out all pending GA events"); + googleAnalyticsTrackers.flush(); + googleAnalyticsTrackers.resetStats(); + } + + public String getAnalyticsToken(@NonNull Config config) { + if (config.hasPath(GA_TOKEN_PATH)) { + return config.getString(GA_TOKEN_PATH); + } + throw new RuntimeException("There is no secret in the SM for the Google Analytics"); + } + + +} diff --git a/src/main/java/org/broadinstitute/dsm/model/filter/participant/BaseFilterParticipantList.java b/src/main/java/org/broadinstitute/dsm/model/filter/participant/BaseFilterParticipantList.java index ba5c6110d..7f3330016 100644 --- a/src/main/java/org/broadinstitute/dsm/model/filter/participant/BaseFilterParticipantList.java +++ b/src/main/java/org/broadinstitute/dsm/model/filter/participant/BaseFilterParticipantList.java @@ -1,15 +1,11 @@ package org.broadinstitute.dsm.model.filter.participant; -import java.time.LocalDate; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - import com.google.gson.Gson; import lombok.NonNull; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; +import org.broadinstitute.dsm.analytics.GoogleAnalyticsMetrics; +import org.broadinstitute.dsm.analytics.GoogleAnalyticsMetricsTracker; import org.broadinstitute.dsm.db.DDPInstance; import org.broadinstitute.dsm.db.ViewFilter; import org.broadinstitute.dsm.db.dao.ddp.instance.DDPInstanceDao; @@ -19,10 +15,9 @@ import org.broadinstitute.dsm.db.structure.DBElement; import org.broadinstitute.dsm.model.Filter; import org.broadinstitute.dsm.model.elasticsearch.ElasticSearch; -import org.broadinstitute.dsm.model.participant.ParticipantWrapper; import org.broadinstitute.dsm.model.filter.BaseFilter; import org.broadinstitute.dsm.model.filter.Filterable; -import org.broadinstitute.dsm.model.participant.ParticipantWrapperDto; +import org.broadinstitute.dsm.model.participant.ParticipantWrapper; import org.broadinstitute.dsm.model.participant.ParticipantWrapperPayload; import org.broadinstitute.dsm.model.participant.ParticipantWrapperResult; import org.broadinstitute.dsm.statics.DBConstants; @@ -31,6 +26,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + public abstract class BaseFilterParticipantList extends BaseFilter implements Filterable { private static final Logger logger = LoggerFactory.getLogger(BaseFilterParticipantList.class); @@ -57,6 +58,7 @@ public BaseFilterParticipantList(String jsonBody) { protected ParticipantWrapperResult filterParticipantList(Filter[] filters, Map columnNameMap, @NonNull DDPInstance instance) { + Long timer = System.currentTimeMillis(); Map queryConditions = new HashMap<>(); List allParticipantData = null; DDPInstanceDto ddpInstanceDto = new DDPInstanceDao().getDDPInstanceByInstanceName(realm).orElseThrow(); @@ -119,9 +121,12 @@ protected ParticipantWrapperResult filterParticipantList(Filter[] filters, Map filter(QueryParamsMap queryParamsMap) { + Long timer = System.currentTimeMillis(); List wrapperList = new ArrayList<>(); if (Objects.isNull(queryParamsMap)) return wrapperList; prepareNeccesaryData(queryParamsMap); @@ -52,6 +55,8 @@ public List filter(QueryParamsMap queryParamsMap) { wrapperList = filterTissueList(filters, PatchUtil.getColumnNameMap(), quickFilterName, ddpInstance, filterQuery); } logger.info("Found " + wrapperList.size() + " tissues for Tissue View"); + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(ddpInstance.getName(), GoogleAnalyticsMetrics.EVENT_CATEGORY_TISSUE_LIST, + GoogleAnalyticsMetrics.EVENT_ACTION_TISSUE_LIST, GoogleAnalyticsMetrics.EVENT_LABEL_TISSUE_LIST, Math.toIntExact((System.currentTimeMillis() - timer)/1000)); return wrapperList; } } diff --git a/src/main/java/org/broadinstitute/dsm/route/PatchRoute.java b/src/main/java/org/broadinstitute/dsm/route/PatchRoute.java index dbd54fba0..2809a0898 100644 --- a/src/main/java/org/broadinstitute/dsm/route/PatchRoute.java +++ b/src/main/java/org/broadinstitute/dsm/route/PatchRoute.java @@ -7,6 +7,8 @@ import lombok.NonNull; import org.apache.commons.lang3.StringUtils; import org.broadinstitute.ddp.handlers.util.Result; +import org.broadinstitute.dsm.analytics.GoogleAnalyticsMetrics; +import org.broadinstitute.dsm.analytics.GoogleAnalyticsMetricsTracker; import org.broadinstitute.dsm.db.*; import org.broadinstitute.dsm.db.dao.ddp.participant.ParticipantDao; import org.broadinstitute.dsm.db.dao.ddp.participant.ParticipantDataDao; @@ -42,6 +44,7 @@ import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; + import static org.broadinstitute.ddp.db.TransactionWrapper.inTransaction; //Class needs to be refactored as soon as possible!!! @@ -132,9 +135,13 @@ else if (EventTypeDao.EVENT.equals(action.getType())) { } } else { + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(ddpInstance.getName(), GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); throw new RuntimeException("DBElement not found in ColumnNameMap: " + nameValue.getName()); } } + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(ddpInstance.getName(), GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); return new Result(200, gson.toJson(nameValues)); } else { @@ -145,10 +152,14 @@ else if (EventTypeDao.EVENT.equals(action.getType())) { List nameValues = setWorkflowRelatedFields(patch); writeDSMRecordsToES(patch, ddpInstance); //return nameValues with nulls + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(ddpInstance.getName(), GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); return new Result(200, gson.toJson(nameValues)); } } else { + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(ddpInstance.getName(), GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); throw new RuntimeException("DBElement not found in ColumnNameMap: " + patch.getNameValue().getName()); } } @@ -177,6 +188,8 @@ else if (StringUtils.isNotBlank(patch.getParent()) && StringUtils.isNotBlank(pat Map map = new HashMap<>(); map.put(PRIMARY_KEY_ID, primaryKeyId); //return map with nulls + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(null, GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); return new Result(200, gson.toJson(map)); } else { @@ -244,6 +257,8 @@ else if (StringUtils.isNotBlank(patch.getParent()) && StringUtils.isNotBlank(pat map.put("oncHistoryDetailId", oncHistoryDetailId); nameValues.add(new NameValue("request", OncHistoryDetail.STATUS_REVIEW)); map.put(NAME_VALUE, gson.toJson(nameValues)); + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(null,GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); //return map with nulls return new Result(200, gson.toJson(map)); } @@ -262,11 +277,10 @@ else if (Patch.ONC_HISTORY_ID.equals(patch.getParent())) { map.put("tissueId", tissueId); if (!nameValues.isEmpty()) { map.put(NAME_VALUE, gson.toJson(nameValues)); - return new Result(200, gson.toJson(map)); } - else { + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(null, GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); return new Result(200, gson.toJson(map)); - } } } else { @@ -301,6 +315,8 @@ else if (EventTypeDao.EVENT.equals(action.getType())) { } } } + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(ddpInstance.getName(), GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); return new Result(200, gson.toJson(map)); } else if (Patch.DDP_PARTICIPANT_ID.equals(patch.getParent())) { @@ -314,20 +330,30 @@ else if (Patch.DDP_PARTICIPANT_ID.equals(patch.getParent())) { throw new RuntimeException("DBElement not found in ColumnNameMap: " + patch.getNameValue().getName()); } Patch.patch(String.valueOf(participantId), patch.getUser(), patch.getNameValue(), dbElement); + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(ddpInstance.getName(), GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); return new Result(200, gson.toJson(Map.of(PARTICIPANT_ID, String.valueOf(participantId)))); } } } + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(null, GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); throw new RuntimeException("Id and parentId was null"); } catch (DuplicateException e) { + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(null, GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); return new Result(500, "Duplicate value"); } catch (Exception e) { + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(null, GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); throw new RuntimeException("An error occurred while attempting to patch ", e); } } else { + GoogleAnalyticsMetricsTracker.getInstance().sendAnalyticsMetrics(null, GoogleAnalyticsMetrics.EVENT_CATEGORY_PATCH_DATA, + GoogleAnalyticsMetrics.EVENT_ACTION_PATCH_DATA, GoogleAnalyticsMetrics.EVENT_LABEL_PATCH_DATA, 1); response.status(500); return new Result(500, UserErrorMessages.NO_RIGHTS); } diff --git a/src/main/java/org/broadinstitute/dsm/statics/RoutePath.java b/src/main/java/org/broadinstitute/dsm/statics/RoutePath.java index 2e9afd15e..5e93291c9 100644 --- a/src/main/java/org/broadinstitute/dsm/statics/RoutePath.java +++ b/src/main/java/org/broadinstitute/dsm/statics/RoutePath.java @@ -10,6 +10,10 @@ public enum RequestMethod { GET, PATCH, POST, PUT } + public static final class GAE { + public static final String STOP_ENDPOINT = "/_ah/stop"; + } + public static final String REALM = "realm"; public static final String KIT_TYPE = "kitType"; public static final String UPLOAD_REASONS = "uploadReasons"; diff --git a/src/main/java/org/broadinstitute/dsm/util/ElasticSearchUtil.java b/src/main/java/org/broadinstitute/dsm/util/ElasticSearchUtil.java index ee2798cc8..87cdb28b3 100644 --- a/src/main/java/org/broadinstitute/dsm/util/ElasticSearchUtil.java +++ b/src/main/java/org/broadinstitute/dsm/util/ElasticSearchUtil.java @@ -116,8 +116,8 @@ public class ElasticSearchUtil { private static Map fieldMappings; static { - initClient(); - fetchFieldMappings(); + initClient(); + fetchFieldMappings(); } public static synchronized void initClient() { diff --git a/src/test/java/org/broadinstitute/dsm/DirectMethodTest.java b/src/test/java/org/broadinstitute/dsm/DirectMethodTest.java index 8f63bf114..c2c42b9a3 100644 --- a/src/test/java/org/broadinstitute/dsm/DirectMethodTest.java +++ b/src/test/java/org/broadinstitute/dsm/DirectMethodTest.java @@ -1,5 +1,10 @@ package org.broadinstitute.dsm; +import com.brsanthu.googleanalytics.GoogleAnalytics; +import com.brsanthu.googleanalytics.GoogleAnalyticsConfig; +import com.brsanthu.googleanalytics.request.DefaultRequest; +import com.brsanthu.googleanalytics.request.EventHit; +import com.brsanthu.googleanalytics.request.GoogleAnalyticsResponse; import com.google.gson.JsonObject; import lombok.NonNull; import org.apache.commons.lang3.StringUtils; @@ -7,10 +12,10 @@ import org.broadinstitute.ddp.util.GoogleBucket; import org.broadinstitute.dsm.db.*; import org.broadinstitute.dsm.db.dto.settings.InstanceSettingsDto; -import org.broadinstitute.dsm.model.NDIUploadObject; import org.broadinstitute.dsm.exception.FileColumnMissing; import org.broadinstitute.dsm.model.KitRequestSettings; import org.broadinstitute.dsm.model.KitType; +import org.broadinstitute.dsm.model.NDIUploadObject; import org.broadinstitute.dsm.model.Value; import org.broadinstitute.dsm.model.gbf.LineItem; import org.broadinstitute.dsm.model.gbf.Orders; @@ -51,6 +56,41 @@ public void beforeTest() { DBTestUtil.deleteAllFieldSettings(TEST_DDP); } + @Test + public void testGA(){ + String realUa = "UA-12345678-1";// dummy value + GoogleAnalytics ga = GoogleAnalytics.builder() + .withConfig(new GoogleAnalyticsConfig().setGatherStats(true).setUserAgent("Custom User Agent")) + .withDefaultRequest(new DefaultRequest().userIp("127.0.0.1").trackingId(realUa)) + .withTrackingId(realUa) + .build(); + ga.resetStats(); + EventHit eventHit = new EventHit("test-dsm", "action-test-dsm", "label-test-dsm", 1); + if (ga != null) { + eventHit = ga.event().eventCategory(eventHit.eventCategory()) + .eventAction(eventHit.eventAction()) + .eventLabel(eventHit.eventLabel()) + .eventValue(eventHit.eventValue()) + .trackingId(realUa); + Assert.assertEquals(eventHit.hitType(), "event"); + GoogleAnalyticsResponse response = ga.event().eventCategory(eventHit.eventCategory()) + .eventAction(eventHit.eventAction()) + .eventLabel(eventHit.eventLabel()) + .eventValue(eventHit.eventValue()) + .trackingId(realUa) + .send(); + + System.out.println(response.getRequestParams()); + System.out.println(response.getStatusCode()); + Assert.assertEquals(response.getStatusCode(), 200); + Assert.assertNotEquals(ga.getStats().getEventHits(), 0); + Assert.assertEquals(ga.getStats().getEventHits(), 1); + + + } + + + } @Test public void getFieldSettingsTest() { //This test assumes that the before method has removed any TEST_DDP settings from the field_settings table