feat: Added more data to existing analytics events (#15684)

* feat: added more data to existing analytics events

* Added extra audit data points for page and action events

* Corrected minor comment issue

* Review changes

* Removed audit references in variable names

* Review changes related to sending analytics events and DB optimization
This commit is contained in:
Vishnu Gp 2022-08-09 18:35:00 +05:30 committed by GitHub
parent ec29bbfac4
commit 2c03cecbb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 19 deletions

View File

@ -115,7 +115,11 @@ public class FieldName {
public static final String THEME = "theme";
public static final String EDIT_MODE_THEME = "editModeTheme";
public static final String FLOW_NAME = "flowName";
public static final String AUDIT_DATA = "auditData";
public static final String EVENT_DATA = "eventData";
public static final String MODE_OF_LOGIN = "modeOfLogin";
public static final String FORM_LOGIN = "FormLogin";
public static final String VIEW_MODE = "viewMode";
public static final String ACTION_EXECUTION_REQUEST = "actionExecutionRequest";
public static final String ACTION_EXECUTION_RESULT = "actionExecutionResult";
public static final String ACTION_EXECUTION_TIME = "actionExecutionTime";
}

View File

@ -164,7 +164,8 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE {
return Mono.just(object);
}
final String eventTag = event.getEventName() + "_" + object.getClass().getSimpleName().toUpperCase();
// In case of action execution, event.getEventName() only is used to support backward compatibility of event name
final String eventTag = AnalyticsEvents.EXECUTE_ACTION.equals(event) ? event.getEventName() : event.getEventName() + "_" + object.getClass().getSimpleName().toUpperCase();
// We will create an anonymous user object for event tracking if no user is present
// Without this, a lot of flows meant for anonymous users will error out
@ -197,8 +198,8 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE {
analyticsProperties.put("oid", object.getId());
if (extraProperties != null) {
analyticsProperties.putAll(extraProperties);
// To avoid sending extra audit data to analytics
analyticsProperties.remove(FieldName.AUDIT_DATA);
// To avoid sending extra event data to analytics
analyticsProperties.remove(FieldName.EVENT_DATA);
}
sendEvent(eventTag, username, analyticsProperties);

View File

@ -1117,7 +1117,7 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
private Mono<Application> sendCloneApplicationAnalyticsEvent(Application sourceApplication, Application application) {
return workspaceService.getById(application.getWorkspaceId())
.flatMap(workspace -> {
final Map<String, Object> auditData = Map.of(
final Map<String, Object> eventData = Map.of(
FieldName.SOURCE_APPLICATION, sourceApplication,
FieldName.APPLICATION, application,
FieldName.WORKSPACE, workspace
@ -1127,7 +1127,7 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
FieldName.SOURCE_APPLICATION_ID, sourceApplication.getId(),
FieldName.APPLICATION_ID, application.getId(),
FieldName.WORKSPACE_ID, workspace.getId(),
FieldName.AUDIT_DATA, auditData
FieldName.EVENT_DATA, eventData
);
return analyticsService.sendObjectEvent(AnalyticsEvents.CLONE, application, data);
@ -1145,13 +1145,12 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
return Mono.empty();
}
//TODO: Add more audit data
final Map<String, Object> auditData = Map.of(
final Map<String, Object> eventData = Map.of(
FieldName.PAGE, newPage
);
final Map<String, Object> data = Map.of(
FieldName.AUDIT_DATA, auditData
FieldName.EVENT_DATA, eventData
);
return analyticsService.sendObjectEvent(AnalyticsEvents.VIEW, newPage, data);

View File

@ -990,13 +990,15 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
ActionExecutionResult actionExecutionResult,
Long timeElapsed
) {
// Since we're loading the application from DB *only* for analytics, we check if analytics is
// active before making the call to DB.
if (!analyticsService.isActive()) {
// This is to have consistency in how the AnalyticsService is being called.
// Even though sendObjectEvent is triggered, AnalyticsService would still reject this and prevent the event
// from being sent to analytics provider if telemetry is disabled.
analyticsService.sendObjectEvent(AnalyticsEvents.EXECUTE_ACTION, action);
return Mono.empty();
}
ActionExecutionRequest actionExecutionRequest = actionExecutionResult.getRequest();
ActionExecutionRequest request;
if (actionExecutionRequest != null) {
@ -1123,8 +1125,18 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
"statusCode", actionExecutionResult.getStatusCode()
));
}
analyticsService.sendEvent(AnalyticsEvents.EXECUTE_ACTION.getEventName(), user.getUsername(), data);
final Map<String, Object> eventData = Map.of(
FieldName.ACTION, action,
FieldName.DATASOURCE, datasource,
FieldName.VIEW_MODE, viewMode,
FieldName.ACTION_EXECUTION_RESULT, actionExecutionResult,
FieldName.ACTION_EXECUTION_TIME, timeElapsed,
FieldName.ACTION_EXECUTION_REQUEST, request,
FieldName.APPLICATION, application,
FieldName.PLUGIN, plugin
);
data.put(FieldName.EVENT_DATA, eventData);
analyticsService.sendObjectEvent(AnalyticsEvents.EXECUTE_ACTION, action, data);
return request;
})
.onErrorResume(error -> {
@ -1860,7 +1872,10 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
if (!StringUtils.hasLength(savedAction.getUnpublishedAction().getPluginName())) {
savedAction.getUnpublishedAction().setPluginName(datasource.getPluginName());
}
return this.getAnalyticsProperties(savedAction);
Map<String, Object> analyticsProperties = this.getAnalyticsProperties(savedAction);
Map<String, Object> eventData = Map.of(FieldName.DATASOURCE, datasource);
analyticsProperties.put(FieldName.EVENT_DATA, eventData);
return analyticsProperties;
}
@Override

View File

@ -22,6 +22,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@ -47,11 +48,14 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
Mono<User> userMono = sessionUserService.getCurrentUser();
// For collecting all the possible event data
Map<String, Object> eventData = new HashMap<>();
Mono<Application> forkApplicationMono = Mono.zip(sourceApplicationMono, targetWorkspaceMono, userMono)
.flatMap(tuple -> {
final Application application = tuple.getT1();
final Workspace targetWorkspace = tuple.getT2();
final User user = tuple.getT3();
eventData.put(FieldName.WORKSPACE, targetWorkspace);
//If the forking application is connected to git, do not copy those data to the new forked application
application.setGitApplicationMetadata(null);
@ -76,7 +80,7 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
final String newApplicationId = applicationIds.get(0);
return applicationService.getById(newApplicationId)
.flatMap(application ->
sendForkApplicationAnalyticsEvent(srcApplicationId, targetWorkspaceId, application));
sendForkApplicationAnalyticsEvent(srcApplicationId, targetWorkspaceId, application, eventData));
});
// Fork application is currently a slow API because it needs to create application, clone all the pages, and then
@ -116,14 +120,15 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
.map(responseUtils::updateApplicationWithDefaultResources);
}
private Mono<Application> sendForkApplicationAnalyticsEvent(String applicationId, String workspaceId, Application application) {
private Mono<Application> sendForkApplicationAnalyticsEvent(String applicationId, String workspaceId, Application application, Map<String, Object> eventData) {
return applicationService.findById(applicationId, AclPermission.READ_APPLICATIONS)
.flatMap(sourceApplication -> {
final Map<String, Object> data = Map.of(
"forkedFromAppId", applicationId,
"forkedToOrgId", workspaceId,
"forkedFromAppName", sourceApplication.getName()
"forkedFromAppName", sourceApplication.getName(),
FieldName.EVENT_DATA, eventData
);
return analyticsService.sendObjectEvent(AnalyticsEvents.FORK, application, data);

View File

@ -2116,7 +2116,7 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
.flatMap(tuple -> {
Application application = tuple.getT1();
Workspace workspace = tuple.getT2();
final Map<String, Object> auditData = Map.of(
final Map<String, Object> eventData = Map.of(
FieldName.APPLICATION, application,
FieldName.WORKSPACE, workspace
);
@ -2124,7 +2124,7 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
final Map<String, Object> data = Map.of(
FieldName.APPLICATION_ID, application.getId(),
FieldName.WORKSPACE_ID, workspace.getId(),
FieldName.AUDIT_DATA, auditData
FieldName.EVENT_DATA, eventData
);
return analyticsService.sendObjectEvent(event, application, data);