From 852d1c2a7a31df6c33602d3a3dee571a3b837e03 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 19 Nov 2024 23:02:04 -0600 Subject: [PATCH] #30443 adding changes for the event source (#30516) Adding the event source + some minor refactoring --- .../collectors/AsyncVanitiesCollector.java | 6 +-- .../collectors/BasicProfileCollector.java | 54 +++++++++++-------- .../analytics/track/collectors/Collector.java | 31 +++++++++++ .../track/collectors/CollectorContextMap.java | 16 ++++++ .../collectors/CustomerEventCollector.java | 25 ++++----- .../track/collectors/EventSource.java | 23 ++++++++ .../track/collectors/FilesCollector.java | 29 +++++----- .../track/collectors/PageDetailCollector.java | 37 ++++++------- .../track/collectors/PagesCollector.java | 45 ++++++++-------- .../collectors/SyncVanitiesCollector.java | 33 ++++++------ .../content/ContentAnalyticsResource.java | 14 ++++- .../RuleAnalyticsFireUserEventActionlet.java | 17 +++--- .../AnalyticsFireUserEventActionlet.java | 17 +++--- ...leAnalyticsFireUserEventActionletTest.java | 10 ++-- .../AnalyticsFireUserEventActionletTest.java | 11 ++-- 15 files changed, 232 insertions(+), 136 deletions(-) create mode 100644 dotCMS/src/main/java/com/dotcms/analytics/track/collectors/EventSource.java diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/AsyncVanitiesCollector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/AsyncVanitiesCollector.java index 3cacf16c4116..0b35afaa977d 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/AsyncVanitiesCollector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/AsyncVanitiesCollector.java @@ -53,8 +53,8 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa // this will be a new event final CachedVanityUrl cachedVanityUrl = (CachedVanityUrl) collectorContextMap.get(Constants.VANITY_URL_OBJECT); - final Host currentHost = (Host)collectorContextMap.get("currentHost"); - final Long languageId = (Long)collectorContextMap.get("langId"); + final Host currentHost = (Host)collectorContextMap.get(CollectorContextMap.CURRENT_HOST); + final Long languageId = (Long)collectorContextMap.get(CollectorContextMap.LANG_ID); final Host site = Try.of(()->this.hostAPI.find(currentHost.getIdentifier(), APILocator.systemUser(), false)).get(); @@ -67,7 +67,7 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa match.get(whoIAM).collect(innerCollectorContextMap, collectorPayloadBean); } - collectorPayloadBean.put("comeFromVanityURL", true); + collectorPayloadBean.put(COME_FROM_VANITY_URL, true); return collectorPayloadBean; } diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/BasicProfileCollector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/BasicProfileCollector.java index 9ef907a85ccb..ddd7056fd0e6 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/BasicProfileCollector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/BasicProfileCollector.java @@ -6,6 +6,7 @@ import com.dotmarketing.business.web.WebAPILocator; import com.dotmarketing.util.PageMode; import com.dotmarketing.util.UtilMethods; +import com.liferay.util.StringPool; import javax.servlet.http.HttpServletRequest; import java.time.Instant; @@ -14,6 +15,10 @@ import java.time.format.DateTimeFormatter; import java.util.Objects; +/** + * Collects the basic profile information for a collector payload bean. + * @author jsanca + */ public class BasicProfileCollector implements Collector { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'"); @@ -28,46 +33,51 @@ public boolean test(CollectorContextMap collectorContextMap) { public CollectorPayloadBean collect(final CollectorContextMap collectorContextMap, final CollectorPayloadBean collectorPayloadBean) { - // todo: add the user id - final String requestId = (String)collectorContextMap.get("requestId"); - final Long time = (Long)collectorContextMap.get("time"); - final String clusterId = (String)collectorContextMap.get("cluster"); - final String serverId = (String)collectorContextMap.get("server"); - final String sessionId = (String)collectorContextMap.get("session"); - final Boolean sessionNew = (Boolean)collectorContextMap.get("sessionNew"); + final String requestId = (String)collectorContextMap.get(CollectorContextMap.REQUEST_ID); + final Long time = (Long)collectorContextMap.get(CollectorContextMap.TIME); + final String clusterId = (String)collectorContextMap.get(CollectorContextMap.CLUSTER); + final String serverId = (String)collectorContextMap.get(CollectorContextMap.SERVER); + final String sessionId = (String)collectorContextMap.get(CollectorContextMap.SESSION); + final Boolean sessionNew = (Boolean)collectorContextMap.get(CollectorContextMap.SESSION_NEW); final Long timestamp = FunctionUtils.getOrDefault(Objects.nonNull(time), () -> time, System::currentTimeMillis); final Instant instant = Instant.ofEpochMilli(timestamp); final ZonedDateTime zonedDateTimeUTC = instant.atZone(ZoneId.of("UTC")); - collectorPayloadBean.put("request_id", requestId); - collectorPayloadBean.put("utc_time", FORMATTER.format(zonedDateTimeUTC)); - collectorPayloadBean.put("cluster", + collectorPayloadBean.put(REQUEST_ID, requestId); + collectorPayloadBean.put(UTC_TIME, FORMATTER.format(zonedDateTimeUTC)); + collectorPayloadBean.put(CLUSTER, FunctionUtils.getOrDefault(Objects.nonNull(clusterId), ()->clusterId, ClusterFactory::getClusterId)); - collectorPayloadBean.put("server", + collectorPayloadBean.put(SERVER, FunctionUtils.getOrDefault(Objects.nonNull(serverId), ()->serverId,()->APILocator.getServerAPI().readServerId())); - collectorPayloadBean.put("sessionId", sessionId); - collectorPayloadBean.put("sessionNew", sessionNew); + collectorPayloadBean.put(SESSION_ID, sessionId); + collectorPayloadBean.put(SESSION_NEW, sessionNew); - if (UtilMethods.isSet(collectorContextMap.get("referer"))) { - collectorPayloadBean.put("referer", collectorContextMap.get("referer").toString()); + if (UtilMethods.isSet(collectorContextMap.get(CollectorContextMap.REFERER))) { + collectorPayloadBean.put(REFERER, collectorContextMap.get(CollectorContextMap.REFERER).toString()); } - if (UtilMethods.isSet(collectorContextMap.get("user-agent"))) { - collectorPayloadBean.put("userAgent", collectorContextMap.get("user-agent").toString()); + if (UtilMethods.isSet(collectorContextMap.get(CollectorContextMap.USER_AGENT))) { + collectorPayloadBean.put(USER_AGENT, collectorContextMap.get(CollectorContextMap.USER_AGENT).toString()); } final HttpServletRequest request = (HttpServletRequest)collectorContextMap.get("request"); - collectorPayloadBean.put("persona", + collectorPayloadBean.put(PERSONA, WebAPILocator.getPersonalizationWebAPI().getContainerPersonalization(request)); - collectorPayloadBean.put("renderMode", PageMode.get(request).toString().replace("_MODE", "")); + collectorPayloadBean.put(RENDER_MODE, PageMode.get(request).toString().replace("_MODE", StringPool.BLANK)); // Include default value for other boolean fields in the Clickhouse table - collectorPayloadBean.put("comeFromVanityURL", false); - collectorPayloadBean.put("isexperimentpage", false); - collectorPayloadBean.put("istargetpage", false); + collectorPayloadBean.put(COME_FROM_VANITY_URL, false); + collectorPayloadBean.put(IS_EXPERIMENT_PAGE, false); + collectorPayloadBean.put(IS_TARGET_PAGE, false); + + if (Objects.nonNull(collectorPayloadBean.get(EVENT_SOURCE))) { + // this is the default event source + collectorPayloadBean.put(EVENT_SOURCE, EventSource.DOT_CMS.getName()); + } + return collectorPayloadBean; } diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/Collector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/Collector.java index 35a0c66196ad..879d8752f5df 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/Collector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/Collector.java @@ -18,6 +18,37 @@ */ public interface Collector { + String CLUSTER = "cluster"; + String COME_FROM_VANITY_URL = "comeFromVanityURL"; + String CONTENT_TYPE_ID = "content_type_id"; + String CONTENT_TYPE_NAME = "content_type_name"; + String CONTENT_TYPE_VAR_NAME = "content_type_var_name"; + String DETAIL_PAGE_URL = "detail_page_url"; + String EVENT_SOURCE = "event_source"; + String EVENT_TYPE = "event_type"; + String HOST = "host"; + String ID = "id"; + String IS_EXPERIMENT_PAGE = "isexperimentpage"; + String IS_TARGET_PAGE = "istargetpage"; + String LANGUAGE = "language"; + String LANGUAGE_ID = "language_id"; + String OBJECT = "object"; + String PERSONA = "persona"; + String REFERER = "referer"; + String RENDER_MODE = "renderMode"; + String REQUEST_ID = "request_id"; + String RESPONSE = "response"; + String RESPONSE_CODE = "response_code"; + String SERVER = "server"; + String SESSION_ID = "sessionId"; + String SESSION_NEW = "sessionNew"; + String SITE = "site"; + String TITLE = "title"; + String URL = "url"; + String USER_AGENT = "userAgent"; + String UTC_TIME = "utc_time"; + String VANITY_QUERY_STRING = "vanity_query_string"; + /** * Test if the collector should run * @param collectorContextMap diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CollectorContextMap.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CollectorContextMap.java index bae69a850e3b..57a932d0d927 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CollectorContextMap.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CollectorContextMap.java @@ -4,6 +4,22 @@ public interface CollectorContextMap { + String REQUEST_ID = "requestId"; + String TIME = "time"; + String CLUSTER = "cluster"; + String SERVER = "server"; + String SESSION = "session"; + String SESSION_NEW = "sessionNew"; + String REFERER = "referer"; + String USER_AGENT = "user-agent"; + String CURRENT_HOST = "currentHost"; + String LANG_ID = "langId"; + String LANG = "lang"; + String URI = "uri"; + String HOST = "host"; + String EVENT_TYPE = "eventType"; + String PAGE_MODE = "pageMode"; + Object get(String key); RequestMatcher getRequestMatcher(); // since we do not have the previous step phase we need to keep this as an object, but will be a RequestMatcher } diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CustomerEventCollector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CustomerEventCollector.java index df617f3d984f..c4f503c9db3f 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CustomerEventCollector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/CustomerEventCollector.java @@ -2,8 +2,8 @@ import com.dotcms.analytics.track.matchers.UserCustomDefinedRequestMatcher; import com.dotmarketing.beans.Host; +import com.liferay.util.StringPool; -import java.util.HashMap; import java.util.Objects; /** @@ -21,17 +21,18 @@ public boolean test(final CollectorContextMap collectorContextMap) { @Override public CollectorPayloadBean collect(final CollectorContextMap collectorContextMap, final CollectorPayloadBean collectorPayloadBean) { - final String uri = (String)collectorContextMap.get("uri"); - final String host = (String)collectorContextMap.get("host"); - final Host site = (Host) collectorContextMap.get("currentHost"); - final String language = (String)collectorContextMap.get("lang"); - collectorPayloadBean.put("url", uri); - collectorPayloadBean.put("host", Objects.nonNull(site)?site.getHostname():host); - collectorPayloadBean.put("language", language); - collectorPayloadBean.put("site", null != site?site.getIdentifier():"unknown"); - final String eventType = (String)collectorContextMap.get("eventType") == null? - EventType.CUSTOM_USER_EVENT.getType():(String)collectorContextMap.get("eventType"); - collectorPayloadBean.put("event_type", eventType); + + final String uri = (String)collectorContextMap.get(CollectorContextMap.URI); + final String host = (String)collectorContextMap.get(CollectorContextMap.HOST); + final Host site = (Host) collectorContextMap.get(CollectorContextMap.CURRENT_HOST); + final String language = (String)collectorContextMap.get(CollectorContextMap.LANG); + collectorPayloadBean.put(URL, uri); + collectorPayloadBean.put(HOST, Objects.nonNull(site)?site.getHostname():host); + collectorPayloadBean.put(LANGUAGE, language); + collectorPayloadBean.put(SITE, null != site?site.getIdentifier():StringPool.UNKNOWN); + final String eventType = collectorContextMap.get(CollectorContextMap.EVENT_TYPE) == null? + EventType.CUSTOM_USER_EVENT.getType():(String)collectorContextMap.get(CollectorContextMap.EVENT_TYPE); + collectorPayloadBean.put(EVENT_TYPE, eventType); return collectorPayloadBean; } diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/EventSource.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/EventSource.java new file mode 100644 index 000000000000..6cf3a1bed9e9 --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/EventSource.java @@ -0,0 +1,23 @@ +package com.dotcms.analytics.track.collectors; + +/** + * Enum for the Event Sources + * @author jsanca + */ +public enum EventSource { + + DOT_CMS("DOT_CMS"), + REST_API("REST_API"), + WORKFLOW("WORKFLOW"), + RULE("RULE"); + + private final String name; + + EventSource(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/FilesCollector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/FilesCollector.java index 650aaf003a2b..5dd95ee8257d 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/FilesCollector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/FilesCollector.java @@ -6,7 +6,6 @@ import com.dotmarketing.exception.DotDataException; import com.dotmarketing.exception.DotSecurityException; import com.dotmarketing.portlets.contentlet.business.ContentletAPI; -import com.dotmarketing.portlets.contentlet.business.HostAPI; import com.dotmarketing.portlets.contentlet.model.Contentlet; import com.dotmarketing.portlets.fileassets.business.FileAssetAPI; import com.liferay.util.StringPool; @@ -45,28 +44,28 @@ public boolean test(CollectorContextMap collectorContextMap) { public CollectorPayloadBean collect(final CollectorContextMap collectorContextMap, final CollectorPayloadBean collectorPayloadBean) { - final String uri = (String)collectorContextMap.get("uri"); - final String host = (String)collectorContextMap.get("host"); - final Host site = (Host) collectorContextMap.get("currentHost"); - final Long languageId = (Long)collectorContextMap.get("langId"); - final String language = (String)collectorContextMap.get("lang"); + final String uri = (String)collectorContextMap.get(CollectorContextMap.URI); + final String host = (String)collectorContextMap.get(CollectorContextMap.HOST); + final Host site = (Host) collectorContextMap.get(CollectorContextMap.CURRENT_HOST); + final Long languageId = (Long)collectorContextMap.get(CollectorContextMap.LANG_ID); + final String language = (String)collectorContextMap.get(CollectorContextMap.LANG); final HashMap fileObject = new HashMap<>(); if (Objects.nonNull(uri) && Objects.nonNull(site) && Objects.nonNull(languageId)) { getFileAsset(uri, site, languageId).ifPresent(fileAsset -> { - fileObject.put("id", fileAsset.getIdentifier()); - fileObject.put("title", fileAsset.getTitle()); - fileObject.put("url", uri); + fileObject.put(ID, fileAsset.getIdentifier()); + fileObject.put(TITLE, fileAsset.getTitle()); + fileObject.put(URL, uri); }); } - collectorPayloadBean.put("object", fileObject); - collectorPayloadBean.put("url", uri); - collectorPayloadBean.put("host", Objects.nonNull(site)?site.getHostname():host); - collectorPayloadBean.put("language", language); - collectorPayloadBean.put("site", null != site?site.getIdentifier():"unknown"); - collectorPayloadBean.put("event_type", EventType.FILE_REQUEST.getType()); + collectorPayloadBean.put(OBJECT, fileObject); + collectorPayloadBean.put(URL, uri); + collectorPayloadBean.put(HOST, Objects.nonNull(site)?site.getHostname():host); + collectorPayloadBean.put(LANGUAGE, language); + collectorPayloadBean.put(SITE, null != site?site.getIdentifier():StringPool.UNKNOWN); + collectorPayloadBean.put(EVENT_TYPE, EventType.FILE_REQUEST.getType()); return collectorPayloadBean; } diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PageDetailCollector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PageDetailCollector.java index 8c1d27186809..2469f671d337 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PageDetailCollector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PageDetailCollector.java @@ -12,6 +12,7 @@ import com.dotmarketing.portlets.htmlpageasset.model.IHTMLPage; import com.dotmarketing.util.Logger; import com.dotmarketing.util.PageMode; +import com.liferay.util.StringPool; import io.vavr.control.Try; import java.util.HashMap; @@ -50,11 +51,11 @@ public boolean test(CollectorContextMap collectorContextMap) { public CollectorPayloadBean collect(final CollectorContextMap collectorContextMap, final CollectorPayloadBean collectorPayloadBean) { - final String uri = (String) collectorContextMap.get("uri"); - final Host site = (Host) collectorContextMap.get("currentHost"); - final Long languageId = (Long) collectorContextMap.get("langId"); - final PageMode pageMode = (PageMode) collectorContextMap.get("pageMode"); - final String language = (String)collectorContextMap.get("lang"); + final String uri = (String) collectorContextMap.get(CollectorContextMap.URI); + final Host site = (Host) collectorContextMap.get(CollectorContextMap.CURRENT_HOST); + final Long languageId = (Long) collectorContextMap.get(CollectorContextMap.LANG_ID); + final PageMode pageMode = (PageMode) collectorContextMap.get(CollectorContextMap.PAGE_MODE); + final String language = (String)collectorContextMap.get(CollectorContextMap.LANG); final UrlMapContext urlMapContext = new UrlMapContext( pageMode, languageId, uri, site, APILocator.systemUser()); @@ -74,29 +75,29 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa .getOrNull(); final HashMap pageObject = new HashMap<>(); - pageObject.put("id", detailPageContent.getIdentifier()); - pageObject.put("title", detailPageContent.getTitle()); - pageObject.put("url", uri); - pageObject.put("detail_page_url", Try.of(detailPageContent::getURI).getOrElse("")); - collectorPayloadBean.put("object", pageObject); + pageObject.put(ID, detailPageContent.getIdentifier()); + pageObject.put(TITLE, detailPageContent.getTitle()); + pageObject.put(URL, uri); + pageObject.put(DETAIL_PAGE_URL, Try.of(detailPageContent::getURI).getOrElse(StringPool.BLANK)); + collectorPayloadBean.put(OBJECT, pageObject); } - collectorPayloadBean.put("event_type", EventType.PAGE_REQUEST.getType()); - collectorPayloadBean.put("url", uri); - collectorPayloadBean.put("language", language); + collectorPayloadBean.put(EVENT_TYPE, EventType.PAGE_REQUEST.getType()); + collectorPayloadBean.put(URL, uri); + collectorPayloadBean.put(LANGUAGE, language); if (Objects.nonNull(site)) { - collectorPayloadBean.put("host", site.getHostname()); + collectorPayloadBean.put(HOST, site.getHostname()); } return collectorPayloadBean; } private boolean isUrlMap(final CollectorContextMap collectorContextMap){ - final String uri = (String)collectorContextMap.get("uri"); - final Long languageId = (Long)collectorContextMap.get("langId"); - final PageMode pageMode = (PageMode)collectorContextMap.get("pageMode"); - final Host site = (Host) collectorContextMap.get("currentHost"); + final String uri = (String)collectorContextMap.get(CollectorContextMap.URI); + final Long languageId = (Long)collectorContextMap.get(CollectorContextMap.LANG_ID); + final PageMode pageMode = (PageMode)collectorContextMap.get(CollectorContextMap.PAGE_MODE); + final Host site = (Host) collectorContextMap.get(CollectorContextMap.CURRENT_HOST); final UrlMapContext urlMapContext = new UrlMapContext( pageMode, languageId, uri, site, APILocator.systemUser()); diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PagesCollector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PagesCollector.java index 3cbadce39d76..90c4c6e55b01 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PagesCollector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/PagesCollector.java @@ -47,13 +47,13 @@ public boolean test(CollectorContextMap collectorContextMap) { public CollectorPayloadBean collect(final CollectorContextMap collectorContextMap, final CollectorPayloadBean collectorPayloadBean) { - final String uri = (String)collectorContextMap.get("uri"); - final Host site = (Host) collectorContextMap.get("currentHost"); - final Long languageId = (Long)collectorContextMap.get("langId"); - final String language = (String)collectorContextMap.get("lang"); - final PageMode pageMode = (PageMode)collectorContextMap.get("pageMode"); + final String uri = (String)collectorContextMap.get(CollectorContextMap.URI); + final Host site = (Host) collectorContextMap.get(CollectorContextMap.CURRENT_HOST); + final Long languageId = (Long)collectorContextMap.get(CollectorContextMap.LANG_ID); + final String language = (String)collectorContextMap.get(CollectorContextMap.LANG); + final PageMode pageMode = (PageMode)collectorContextMap.get(CollectorContextMap.PAGE_MODE); final HashMap pageObject = new HashMap<>(); - collectorPayloadBean.put("event_type", EventType.PAGE_REQUEST.getType()); + collectorPayloadBean.put(EVENT_TYPE, EventType.PAGE_REQUEST.getType()); if (Objects.nonNull(uri) && Objects.nonNull(site) && Objects.nonNull(languageId)) { final boolean isUrlMap = isUrlMap(collectorContextMap); @@ -70,28 +70,31 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa final URLMapInfo urlMapInfo = urlMappedContent.get(); final Contentlet urlMapContentlet = urlMapInfo.getContentlet(); final ContentType urlMapContentType = urlMapContentlet.getContentType(); - pageObject.put("id", urlMapContentlet.getIdentifier()); - pageObject.put("title", urlMapContentlet.getTitle()); - pageObject.put("content_type_id", urlMapContentType.id()); - pageObject.put("content_type_name", urlMapContentType.name()); - pageObject.put("content_type_var_name", urlMapContentType.variable()); - collectorPayloadBean.put("event_type", EventType.URL_MAP.getType()); + pageObject.put(ID, urlMapContentlet.getIdentifier()); + pageObject.put(TITLE, urlMapContentlet.getTitle()); + pageObject.put(CONTENT_TYPE_ID, urlMapContentType.id()); + pageObject.put(CONTENT_TYPE_NAME, urlMapContentType.name()); + pageObject.put(CONTENT_TYPE_VAR_NAME, urlMapContentType.variable()); + collectorPayloadBean.put(EVENT_TYPE, EventType.URL_MAP.getType()); } } else { final IHTMLPage page = Try.of(() -> this.pageAPI.getPageByPath(uri, site, languageId, true)).get(); + pageObject.put(ID, page.getIdentifier()); + pageObject.put(TITLE, page.getTitle()); + collectorPayloadBean.put(EVENT_TYPE, EventType.PAGE_REQUEST.getType()); pageObject.put("id", page.getIdentifier()); pageObject.put("title", page.getTitle()); } - pageObject.put("url", uri); + pageObject.put(URL, uri); } - collectorPayloadBean.put("object", pageObject); - collectorPayloadBean.put("url", uri); - collectorPayloadBean.put("language", language); + collectorPayloadBean.put(OBJECT, pageObject); + collectorPayloadBean.put(URL, uri); + collectorPayloadBean.put(LANGUAGE, language); if (Objects.nonNull(site)) { - collectorPayloadBean.put("host", site.getHostname()); + collectorPayloadBean.put(HOST, site.getHostname()); } return collectorPayloadBean; @@ -99,10 +102,10 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa private boolean isUrlMap(final CollectorContextMap collectorContextMap){ - final String uri = (String)collectorContextMap.get("uri"); - final Long languageId = (Long)collectorContextMap.get("langId"); - final PageMode pageMode = (PageMode)collectorContextMap.get("pageMode"); - final Host currentHost = (Host) collectorContextMap.get("currentHost"); + final String uri = (String)collectorContextMap.get(CollectorContextMap.URI); + final Long languageId = (Long)collectorContextMap.get(CollectorContextMap.LANG_ID); + final PageMode pageMode = (PageMode)collectorContextMap.get(CollectorContextMap.PAGE_MODE); + final Host currentHost = (Host) collectorContextMap.get(CollectorContextMap.CURRENT_HOST); final UrlMapContext urlMapContext = new UrlMapContext( pageMode, languageId, uri, currentHost, APILocator.systemUser()); diff --git a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/SyncVanitiesCollector.java b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/SyncVanitiesCollector.java index dbec9fe69f84..4f3e3dd1471a 100644 --- a/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/SyncVanitiesCollector.java +++ b/dotCMS/src/main/java/com/dotcms/analytics/track/collectors/SyncVanitiesCollector.java @@ -18,6 +18,7 @@ public class SyncVanitiesCollector implements Collector { public static final String VANITY_URL_KEY = "vanity_url"; + public static final String FORWARD_TO = "forward_to"; public SyncVanitiesCollector() { } @@ -38,35 +39,35 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa final String vanityQueryString = (String)request.getAttribute(Constants.CMS_FILTER_QUERY_STRING_OVERRIDE); if (request instanceof VanityUrlRequestWrapper) { final VanityUrlRequestWrapper vanityRequest = (VanityUrlRequestWrapper) request; - collectorPayloadBean.put("response_code", vanityRequest.getResponseCode()); + collectorPayloadBean.put(RESPONSE_CODE, vanityRequest.getResponseCode()); } collectorPayloadBean.put(VANITY_URL_KEY, vanityUrl); - collectorPayloadBean.put("vanity_query_string", vanityQueryString); + collectorPayloadBean.put(VANITY_QUERY_STRING, vanityQueryString); } - final String uri = (String)collectorContextMap.get("uri"); - final Host site = (Host) collectorContextMap.get("currentHost"); - final Long languageId = (Long)collectorContextMap.get("langId"); - final String language = (String)collectorContextMap.get("lang"); + final String uri = (String)collectorContextMap.get(CollectorContextMap.URI); + final Host site = (Host) collectorContextMap.get(CollectorContextMap.CURRENT_HOST); + final Long languageId = (Long)collectorContextMap.get(CollectorContextMap.LANG_ID); + final String language = (String)collectorContextMap.get(CollectorContextMap.LANG); final CachedVanityUrl cachedVanityUrl = (CachedVanityUrl)collectorContextMap.get(Constants.VANITY_URL_OBJECT); final HashMap vanityObject = new HashMap<>(); if (Objects.nonNull(cachedVanityUrl)) { - vanityObject.put("id", cachedVanityUrl.vanityUrlId); - vanityObject.put("forward_to", collectorPayloadBean.get(VANITY_URL_KEY) != null + vanityObject.put(ID, cachedVanityUrl.vanityUrlId); + vanityObject.put(FORWARD_TO, collectorPayloadBean.get(VANITY_URL_KEY) != null ? (String) collectorPayloadBean.get(VANITY_URL_KEY) : cachedVanityUrl.forwardTo); - vanityObject.put("url", cachedVanityUrl.url); - vanityObject.put("response", String.valueOf(cachedVanityUrl.response)); + vanityObject.put(URL, cachedVanityUrl.url); + vanityObject.put(RESPONSE, String.valueOf(cachedVanityUrl.response)); } - collectorPayloadBean.put("object", vanityObject); - collectorPayloadBean.put("url", uri); - collectorPayloadBean.put("language", language); - collectorPayloadBean.put("language_id", languageId); - collectorPayloadBean.put("site", site.getIdentifier()); - collectorPayloadBean.put("event_type", EventType.VANITY_REQUEST.getType()); + collectorPayloadBean.put(OBJECT, vanityObject); + collectorPayloadBean.put(URL, uri); + collectorPayloadBean.put(LANGUAGE, language); + collectorPayloadBean.put(LANGUAGE_ID, languageId); + collectorPayloadBean.put(SITE, site.getIdentifier()); + collectorPayloadBean.put(EVENT_TYPE, EventType.VANITY_REQUEST.getType()); return collectorPayloadBean; } diff --git a/dotCMS/src/main/java/com/dotcms/rest/api/v1/analytics/content/ContentAnalyticsResource.java b/dotCMS/src/main/java/com/dotcms/rest/api/v1/analytics/content/ContentAnalyticsResource.java index ca36973aad2c..b1cdc0303dd0 100644 --- a/dotCMS/src/main/java/com/dotcms/rest/api/v1/analytics/content/ContentAnalyticsResource.java +++ b/dotCMS/src/main/java/com/dotcms/rest/api/v1/analytics/content/ContentAnalyticsResource.java @@ -3,6 +3,8 @@ import com.dotcms.analytics.content.ContentAnalyticsAPI; import com.dotcms.analytics.content.ReportResponse; import com.dotcms.analytics.model.ResultSetItem; +import com.dotcms.analytics.track.collectors.Collector; +import com.dotcms.analytics.track.collectors.EventSource; import com.dotcms.analytics.track.collectors.WebEventsCollectorServiceFactory; import com.dotcms.analytics.track.matchers.UserCustomDefinedRequestMatcher; import com.dotcms.rest.InitDataObject; @@ -20,6 +22,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import java.io.Serializable; +import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -235,9 +238,18 @@ public ResponseEntityStringView fireUserCustomEvent(@Context final HttpServletRe DotPreconditions.checkNotNull(userEventPayload, IllegalArgumentException.class, "The 'userEventPayload' JSON cannot be null"); DotPreconditions.checkNotNull(userEventPayload.get("event_type"), IllegalArgumentException.class, "The 'event_type' field is required"); + if (userEventPayload.containsKey(Collector.EVENT_SOURCE)) { + throw new IllegalArgumentException("The 'event_source' field is reserved and cannot be used"); + } Logger.debug(this, ()->"Creating an user custom event with the payload: " + userEventPayload); request.setAttribute("requestId", Objects.nonNull(request.getAttribute("requestId")) ? request.getAttribute("requestId") : UUIDUtil.uuid()); - WebEventsCollectorServiceFactory.getInstance().getWebEventsCollectorService().fireCollectorsAndEmitEvent(request, response, USER_CUSTOM_DEFINED_REQUEST_MATCHER, userEventPayload); + + final Map userEventPayloadWithDefaults = new HashMap<>(userEventPayload); + userEventPayloadWithDefaults.put(Collector.EVENT_SOURCE, EventSource.REST_API.getName()); + + WebEventsCollectorServiceFactory.getInstance().getWebEventsCollectorService().fireCollectorsAndEmitEvent(request, response, + USER_CUSTOM_DEFINED_REQUEST_MATCHER, userEventPayloadWithDefaults); + return new ResponseEntityStringView("User event created successfully"); } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionlet.java b/dotCMS/src/main/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionlet.java index 9ddb5e134035..42e0b1eb9a90 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionlet.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionlet.java @@ -1,5 +1,7 @@ package com.dotmarketing.portlets.rules.actionlet; +import com.dotcms.analytics.track.collectors.Collector; +import com.dotcms.analytics.track.collectors.EventSource; import com.dotcms.analytics.track.collectors.WebEventsCollectorService; import com.dotcms.analytics.track.collectors.WebEventsCollectorServiceFactory; import com.dotcms.analytics.track.matchers.UserCustomDefinedRequestMatcher; @@ -36,10 +38,6 @@ public class RuleAnalyticsFireUserEventActionlet extends RuleActionlet objectDetail = new HashMap<>(); final Map userEventPayload = new HashMap<>(); - userEventPayload.put(RULE_ID, Objects.nonNull(instance.objectId) ? instance.objectId : identifier); + userEventPayload.put(Collector.ID, Objects.nonNull(instance.objectId) ? instance.objectId : identifier); - objectDetail.put(RULE_ID, identifier); - objectDetail.put(RULE_OBJECT_CONTENT_TYPE_VAR_NAME, Objects.nonNull(instance.objectType) ? instance.objectType : RULE_CONTENT); - userEventPayload.put(RULE_OBJECT, objectDetail); - userEventPayload.put(RULE_EVENT_TYPE1, instance.eventType); + objectDetail.put(Collector.ID, identifier); + objectDetail.put(Collector.CONTENT_TYPE_VAR_NAME, Objects.nonNull(instance.objectType) ? instance.objectType : RULE_CONTENT); + userEventPayload.put(Collector.OBJECT, objectDetail); + userEventPayload.put(Collector.EVENT_TYPE, instance.eventType); + userEventPayload.put(Collector.EVENT_SOURCE, EventSource.RULE.getName()); webEventsCollectorService.fireCollectorsAndEmitEvent(request, response, USER_CUSTOM_DEFINED_REQUEST_MATCHER, userEventPayload); return true; diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionlet.java b/dotCMS/src/main/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionlet.java index 384a9a8ebe09..3c2af5e7309b 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionlet.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionlet.java @@ -1,5 +1,7 @@ package com.dotmarketing.portlets.workflows.actionlet; +import com.dotcms.analytics.track.collectors.Collector; +import com.dotcms.analytics.track.collectors.EventSource; import com.dotcms.analytics.track.collectors.WebEventsCollectorService; import com.dotcms.analytics.track.collectors.WebEventsCollectorServiceFactory; import com.dotcms.analytics.track.matchers.UserCustomDefinedRequestMatcher; @@ -36,10 +38,6 @@ public class AnalyticsFireUserEventActionlet extends WorkFlowActionlet { public static final String OBJECT_ID = "objectId"; public static final String REQUEST_ID = "requestId"; public static final String CONTENT = "CONTENT"; - public static final String ID = "id"; - public static final String OBJECT_CONTENT_TYPE_VAR_NAME = "object_content_type_var_name"; - public static final String OBJECT = "object"; - public static final String EVENT_TYPE1 = "event_type"; public static final String EVENT_TYPE_DISPLAY = "Event type"; public static final String OBJECT_TYPE_DISPLAY = "Object type"; public static final String OBJECT_ID_DISPLAY = "Object ID"; @@ -95,12 +93,13 @@ public void executeAction(final WorkflowProcessor processor, final HashMap objectDetail = new HashMap<>(); final Map userEventPayload = new HashMap<>(); - userEventPayload.put(ID, UtilMethods.isSet(objectId) ? objectId.trim() : identifier); + userEventPayload.put(Collector.ID, UtilMethods.isSet(objectId) ? objectId.trim() : identifier); - objectDetail.put(ID, identifier); - objectDetail.put(OBJECT_CONTENT_TYPE_VAR_NAME, UtilMethods.isSet(objectType) ? objectType.trim() : CONTENT); - userEventPayload.put(OBJECT, objectDetail); - userEventPayload.put(EVENT_TYPE1, UtilMethods.isSet(eventType)? eventType.trim(): eventType); + objectDetail.put(Collector.ID, identifier); + objectDetail.put(Collector.CONTENT_TYPE_VAR_NAME, UtilMethods.isSet(objectType) ? objectType.trim() : CONTENT); + userEventPayload.put(Collector.OBJECT, objectDetail); + userEventPayload.put(Collector.EVENT_SOURCE, EventSource.WORKFLOW.getName()); + userEventPayload.put(Collector.EVENT_TYPE, UtilMethods.isSet(eventType)? eventType.trim(): eventType); webEventsCollectorService.fireCollectorsAndEmitEvent(request, response, USER_CUSTOM_DEFINED_REQUEST_MATCHER, userEventPayload); } else { Logger.warn(this, "The request or response is null, can't send the event for the contentlet: " + identifier); diff --git a/dotCMS/src/test/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionletTest.java b/dotCMS/src/test/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionletTest.java index 8cf5521fbb26..3031cdbc4214 100644 --- a/dotCMS/src/test/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionletTest.java +++ b/dotCMS/src/test/java/com/dotmarketing/portlets/rules/actionlet/RuleAnalyticsFireUserEventActionletTest.java @@ -54,13 +54,13 @@ public void fireCollectorsAndEmitEvent(HttpServletRequest request, HttpServletRe RequestMatcher requestMatcher, Map userEventPayload) { Assert.assertNotNull(userEventPayload); - Assert.assertEquals("page", userEventPayload.get("event_type")); - Assert.assertEquals("345", userEventPayload.get("id")); + Assert.assertEquals("page", userEventPayload.get(Collector.EVENT_TYPE)); + Assert.assertEquals("345", userEventPayload.get(Collector.ID)); - final Map object = (Map) userEventPayload.get("object"); + final Map object = (Map) userEventPayload.get(Collector.OBJECT); Assert.assertNotNull(object); - Assert.assertEquals("123", object.get("id")); - Assert.assertEquals("CONTENT", object.get("object_content_type_var_name")); + Assert.assertEquals("123", object.get(Collector.ID)); + Assert.assertEquals("CONTENT", object.get(Collector.CONTENT_TYPE_VAR_NAME)); } }; diff --git a/dotCMS/src/test/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionletTest.java b/dotCMS/src/test/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionletTest.java index acf816da10f0..e5d9d8ab42d6 100644 --- a/dotCMS/src/test/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionletTest.java +++ b/dotCMS/src/test/java/com/dotmarketing/portlets/workflows/actionlet/AnalyticsFireUserEventActionletTest.java @@ -1,6 +1,7 @@ package com.dotmarketing.portlets.workflows.actionlet; import com.dotcms.analytics.track.collectors.Collector; +import com.dotcms.analytics.track.collectors.EventSource; import com.dotcms.analytics.track.collectors.WebEventsCollectorService; import com.dotcms.analytics.track.matchers.RequestMatcher; import com.dotcms.api.web.HttpServletRequestThreadLocal; @@ -55,13 +56,13 @@ public void removeCollector(String collectorId) { public void fireCollectorsAndEmitEvent(HttpServletRequest request, HttpServletResponse response, RequestMatcher requestMatcher, Map userEventPayload) { Assert.assertNotNull(userEventPayload); - Assert.assertEquals("page", userEventPayload.get("event_type")); - Assert.assertEquals("123", userEventPayload.get("id")); + Assert.assertEquals(EventSource.WORKFLOW.getName(), userEventPayload.get(Collector.EVENT_SOURCE)); + Assert.assertEquals("123", userEventPayload.get(Collector.ID)); - final Map object = (Map) userEventPayload.get("object"); + final Map object = (Map) userEventPayload.get(Collector.OBJECT); Assert.assertNotNull(object); - Assert.assertEquals("123", object.get("id")); - Assert.assertEquals("CONTENT", object.get("object_content_type_var_name")); + Assert.assertEquals("123", object.get(Collector.ID)); + Assert.assertEquals("CONTENT", object.get(Collector.CONTENT_TYPE_VAR_NAME)); } }; final AnalyticsFireUserEventActionlet analyticsFireUserEventActionlet = new AnalyticsFireUserEventActionlet(webEventsCollectorService);