Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(Content Analytics) #31319 : Add telemetry customer category, customer name, and environment name to Content Analytics events #31459

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ CREATE TABLE IF NOT EXISTS clickhouse_test_db.events
_timestamp DateTime,
api_key String,
cluster_id String,
customer_name String,
customer_category String,
environment_name String,
environment_version String,
customer_id String,
doc_encoding String,
doc_host String,
Expand Down Expand Up @@ -110,3 +114,9 @@ ALTER TABLE clickhouse_test_db.events DROP COLUMN IF EXISTS object_detail_page_u
ALTER TABLE clickhouse_test_db.events DROP COLUMN IF EXISTS object_url;
ALTER TABLE clickhouse_test_db.events DROP COLUMN IF EXISTS object_forward_to;
ALTER TABLE clickhouse_test_db.events DROP COLUMN IF EXISTS comefromvanityurl;


ALTER TABLE clickhouse_test_db.events ADD COLUMN IF NOT EXISTS customer_name String;
ALTER TABLE clickhouse_test_db.events ADD COLUMN IF NOT EXISTS customer_category String;
ALTER TABLE clickhouse_test_db.events ADD COLUMN IF NOT EXISTS environment_name String;
ALTER TABLE clickhouse_test_db.events ADD COLUMN IF NOT EXISTS environment_version String;
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
package com.dotcms.analytics.track.collectors;

import com.dotcms.enterprise.cluster.ClusterFactory;
import com.dotcms.exception.ExceptionUtil;
import com.dotcms.telemetry.business.MetricsAPI;
import com.dotcms.util.FunctionUtils;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.web.WebAPILocator;
import com.dotmarketing.util.PageMode;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UtilMethods;
import com.liferay.portal.model.User;
import com.liferay.util.StringPool;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* Collects the basic profile information for a collector payload bean.
* Collects the basic profile information for a collector payload bean. It's worth noting that
* <b>ALL</b>ALL data collectors will include the information added by this one.
*
* @author jsanca
* @since Sep 17th, 2024
*/
public class BasicProfileCollector implements Collector {

Expand Down Expand Up @@ -56,6 +60,8 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa
collectorPayloadBean.put(SESSION_ID, sessionId);
collectorPayloadBean.put(SESSION_NEW, sessionNew);

this.setCustomerTelemetryData(collectorPayloadBean);

if (UtilMethods.isSet(collectorContextMap.get(CollectorContextMap.REFERER))) {
collectorPayloadBean.put(REFERER, collectorContextMap.get(CollectorContextMap.REFERER).toString());
}
Expand Down Expand Up @@ -83,13 +89,34 @@ public CollectorPayloadBean collect(final CollectorContextMap collectorContextMa
return collectorPayloadBean;
}

/**
* Sets the customer Telemetry data as part of the information that will be persisted to the
* Content Analytics database.
*
* @param collectorPayloadBean The {@link CollectorPayloadBean} that will be persisted to the
* Content Analytics database.
*/
private void setCustomerTelemetryData(final CollectorPayloadBean collectorPayloadBean) {
final MetricsAPI metricsAPI = APILocator.getMetricsAPI();
try {
final MetricsAPI.Client client = metricsAPI.getClient();
collectorPayloadBean.put(CUSTOMER_NAME, client.getClientName());
collectorPayloadBean.put(CUSTOMER_CATEGORY, client.getCategory());
collectorPayloadBean.put(ENVIRONMENT_NAME, client.getEnvironment());
collectorPayloadBean.put(ENVIRONMENT_VERSION, client.getVersion());
} catch (final DotDataException e) {
Logger.warnAndDebug(BasicProfileCollector.class, String.format("Failed to retrieve customer Telemetry data: " +
"%s", ExceptionUtil.getErrorMessage(e)), e);
}
}

private void setUserInfo(final HttpServletRequest request, final CollectorPayloadBean collectorPayloadBean) {

final User user = WebAPILocator.getUserWebAPI().getUser(request);
if (Objects.nonNull(user)) {

final HashMap<String, String> userObject = new HashMap<>();
userObject.put(ID, user.getUserId().toString());
userObject.put(ID, user.getUserId());
userObject.put(EMAIL, user.getEmailAddress());
collectorPayloadBean.put(USER_OBJECT, userObject);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,9 @@ public interface Collector {
String USER_AGENT = "userAgent";
String UTC_TIME = "utc_time";


String RESPONSE = "action";
String RESPONSE_CODE = "response_code";


String DETAIL_PAGE_URL = "detail_page_url";
String IS_EXPERIMENT_PAGE = "isexperimentpage";
String IS_TARGET_PAGE = "istargetpage";
Expand All @@ -61,6 +59,12 @@ public interface Collector {

String EMAIL = "email";
String USER_OBJECT = "user";

String CUSTOMER_NAME = "customer_name";
String CUSTOMER_CATEGORY = "customer_category";
String ENVIRONMENT_NAME = "environment_name";
String ENVIRONMENT_VERSION = "environment_version";

/**
* Test if the collector should run
* @param collectorContextMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import com.dotcms.util.IntegrationTestInitService;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.UUIDUtil;
import com.dotmarketing.util.UtilMethods;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

Expand All @@ -22,6 +24,8 @@
import static org.mockito.Mockito.mock;

/**
* Verifies that the {@link BasicProfileCollector} is able to collect the basic profile data and
* works as expected.
*
* @author Jose Castro
* @since Oct 9th, 2024
Expand All @@ -31,6 +35,12 @@ public class BasicProfileCollectorTest extends IntegrationTestBase {
private static String CLUSTER_ID = null;
private static String SERVER_ID = null;

private static final String TEST_CUSTOMER_NAME = "test-customer-name";
private static final String TEST_CUSTOMER_CATEGORY = "test-customer-category";
private static final String TEST_ENVIRONMENT_NAME = "test-environment-name";

private static final int TEST_ENVIRONMENT_VERSION = 123;

@BeforeClass
public static void prepare() throws Exception {
// Setting web app environment
Expand All @@ -39,13 +49,32 @@ public static void prepare() throws Exception {

CLUSTER_ID = APILocator.getShortyAPI().shortify(ClusterFactory.getClusterId());
SERVER_ID = APILocator.getShortyAPI().shortify(APILocator.getServerAPI().readServerId());

// Setting test values for specific Telemetry env vars
Config.setProperty("TELEMETRY_CLIENT_NAME", TEST_CUSTOMER_NAME);
Config.setProperty("TELEMETRY_CLIENT_CATEGORY", TEST_CUSTOMER_CATEGORY);
Config.setProperty("TELEMETRY_CLIENT_ENV", TEST_ENVIRONMENT_NAME);
Config.setProperty("TELEMETRY_CLIENT_VERSION", TEST_ENVIRONMENT_VERSION);
}

@AfterClass
public static void afterClass() {
// Re-setting the Telemetry env vars
Config.setProperty("TELEMETRY_CLIENT_NAME", null);
Config.setProperty("TELEMETRY_CLIENT_CATEGORY", null);
Config.setProperty("TELEMETRY_CLIENT_ENV", null);
Config.setProperty("TELEMETRY_CLIENT_ENV", null);
}

/**
* <ul>
* <li><b>Method to test: </b>{@link }</li>
* <li><b>Given Scenario: </b></li>
* <li><b>Expected Result: </b></li>
* <li><b>Method to test:</b>
* {@link BasicProfileCollector#collect(CollectorContextMap, CollectorPayloadBean)}</li>
* <li><b>Given Scenario:</b> Simulate the collection of Basic Profile data, which is
* data that is ALWAYS collected for any kind of Data Collector, and compare it with an
* expected data map.</li>
* <li><b>Expected Result:</b> Both the collected data map and the expected data must
* match.</li>
* </ul>
*/
@Test
Expand All @@ -54,7 +83,7 @@ public void collectBasicProfileData() throws DotDataException, UnknownHostExcept
final String requestId = UUIDUtil.uuid();
final HttpServletRequest request = Util.mockHttpRequestObj(response, "/", requestId,
APILocator.getUserAPI().getAnonymousUser());
final Map<String, Object> expectedDataMap = Map.of(
final Map<String, Object> expectedDataMap = new java.util.HashMap<>(Map.of(
Collector.CLUSTER, CLUSTER_ID,
Collector.SERVER, SERVER_ID,
Collector.PERSONA, "dot:default",
Expand All @@ -63,11 +92,25 @@ public void collectBasicProfileData() throws DotDataException, UnknownHostExcept
Collector.USER_AGENT, Util.USER_AGENT,
Collector.SESSION_ID, "DAA3339CD687D9ABD4101CF9EDDD42DB",
Collector.REQUEST_ID, requestId
);
));
expectedDataMap.putAll(Map.of(
Collector.EVENT_SOURCE, EventSource.DOT_CMS.getName(),
Collector.IS_TARGET_PAGE, false,
Collector.IS_EXPERIMENT_PAGE, false,
Collector.USER_OBJECT, Map.of(
"identifier", "anonymous",
"email", "[email protected]")));
expectedDataMap.putAll(Map.of(
Collector.CUSTOMER_NAME, TEST_CUSTOMER_NAME,
Collector.CUSTOMER_CATEGORY, TEST_CUSTOMER_CATEGORY,
Collector.ENVIRONMENT_NAME, TEST_ENVIRONMENT_NAME,
Collector.ENVIRONMENT_VERSION, TEST_ENVIRONMENT_VERSION
));
final Collector collector = new BasicProfileCollector();
final CollectorPayloadBean collectedData = Util.getCollectorPayloadBean(request, collector, new PagesAndUrlMapsRequestMatcher(), null);

assertTrue("Collected data map cannot be null or empty", UtilMethods.isSet(collectedData));
assertEquals("Collected data map must have the same number of items as expected map", collectedData.toMap().size(), expectedDataMap.size());

int counter = 0;
for (final String key : expectedDataMap.keySet()) {
Expand Down
Loading