Added logs and analytics (#3622)
* Added logs and analytics * Fix in error string Co-authored-by: Shri <shrikant@appsmith.com> * Review fixes :) Co-authored-by: Shri <shrikant@appsmith.com> Co-authored-by: Shri <shrikant@appsmith.com>
This commit is contained in:
parent
bb1d0059d3
commit
93d5a061e2
|
|
@ -8,6 +8,7 @@ public enum AnalyticsEvents {
|
||||||
DELETE,
|
DELETE,
|
||||||
FIRST_LOGIN,
|
FIRST_LOGIN,
|
||||||
EXECUTE_ACTION("execute_ACTION_TRIGGERED"),
|
EXECUTE_ACTION("execute_ACTION_TRIGGERED"),
|
||||||
|
UPDATE_LAYOUT,
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String eventName;
|
private final String eventName;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ public enum AppsmithError {
|
||||||
" \"widgetName\" : \"{1}\"," +
|
" \"widgetName\" : \"{1}\"," +
|
||||||
" \"widgetId\" : \"{2}\"," +
|
" \"widgetId\" : \"{2}\"," +
|
||||||
" \"pageId\" : \"{4}\"," +
|
" \"pageId\" : \"{4}\"," +
|
||||||
" \"layoutId\" : \"{5}\"",
|
" \"layoutId\" : \"{5}\"," +
|
||||||
|
" \"dynamicBinding\" : \"{6}\"",
|
||||||
AppsmithErrorAction.LOG_EXTERNALLY),
|
AppsmithErrorAction.LOG_EXTERNALLY),
|
||||||
USER_ALREADY_EXISTS_IN_ORGANIZATION(400, 4021, "The user {0} has already been added to the organization with role {1}. To change the role, please navigate to `Manage Users` page.", AppsmithErrorAction.DEFAULT),
|
USER_ALREADY_EXISTS_IN_ORGANIZATION(400, 4021, "The user {0} has already been added to the organization with role {1}. To change the role, please navigate to `Manage Users` page.", AppsmithErrorAction.DEFAULT),
|
||||||
UNAUTHORIZED_DOMAIN(401, 4019, "Invalid email domain {0} used for sign in/sign up. Please contact the administrator to configure this domain if this is unexpected.", AppsmithErrorAction.DEFAULT),
|
UNAUTHORIZED_DOMAIN(401, 4019, "Invalid email domain {0} used for sign in/sign up. Please contact the administrator to configure this domain if this is unexpected.", AppsmithErrorAction.DEFAULT),
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,12 @@ package com.appsmith.server.services;
|
||||||
|
|
||||||
import com.appsmith.external.helpers.MustacheHelper;
|
import com.appsmith.external.helpers.MustacheHelper;
|
||||||
import com.appsmith.external.models.ActionConfiguration;
|
import com.appsmith.external.models.ActionConfiguration;
|
||||||
|
import com.appsmith.server.constants.AnalyticsEvents;
|
||||||
import com.appsmith.server.constants.FieldName;
|
import com.appsmith.server.constants.FieldName;
|
||||||
import com.appsmith.server.domains.ActionDependencyEdge;
|
import com.appsmith.server.domains.ActionDependencyEdge;
|
||||||
import com.appsmith.server.domains.Layout;
|
import com.appsmith.server.domains.Layout;
|
||||||
|
import com.appsmith.server.domains.NewPage;
|
||||||
|
import com.appsmith.server.domains.User;
|
||||||
import com.appsmith.server.dtos.ActionDTO;
|
import com.appsmith.server.dtos.ActionDTO;
|
||||||
import com.appsmith.server.dtos.ActionMoveDTO;
|
import com.appsmith.server.dtos.ActionMoveDTO;
|
||||||
import com.appsmith.server.dtos.DslActionDTO;
|
import com.appsmith.server.dtos.DslActionDTO;
|
||||||
|
|
@ -31,6 +34,7 @@ import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -53,6 +57,8 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
||||||
private final NewPageService newPageService;
|
private final NewPageService newPageService;
|
||||||
private final NewActionService newActionService;
|
private final NewActionService newActionService;
|
||||||
private final PageLoadActionsUtil pageLoadActionsUtil;
|
private final PageLoadActionsUtil pageLoadActionsUtil;
|
||||||
|
private final SessionUserService sessionUserService;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To replace fetchUsers in `{{JSON.stringify(fetchUsers)}}` with getUsers, the following regex is required :
|
* To replace fetchUsers in `{{JSON.stringify(fetchUsers)}}` with getUsers, the following regex is required :
|
||||||
|
|
@ -65,12 +71,15 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
||||||
public LayoutActionServiceImpl(ObjectMapper objectMapper,
|
public LayoutActionServiceImpl(ObjectMapper objectMapper,
|
||||||
AnalyticsService analyticsService,
|
AnalyticsService analyticsService,
|
||||||
NewPageService newPageService,
|
NewPageService newPageService,
|
||||||
NewActionService newActionService, PageLoadActionsUtil pageLoadActionsUtil) {
|
NewActionService newActionService,
|
||||||
|
PageLoadActionsUtil pageLoadActionsUtil,
|
||||||
|
SessionUserService sessionUserService) {
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
this.analyticsService = analyticsService;
|
this.analyticsService = analyticsService;
|
||||||
this.newPageService = newPageService;
|
this.newPageService = newPageService;
|
||||||
this.newActionService = newActionService;
|
this.newActionService = newActionService;
|
||||||
this.pageLoadActionsUtil = pageLoadActionsUtil;
|
this.pageLoadActionsUtil = pageLoadActionsUtil;
|
||||||
|
this.sessionUserService = sessionUserService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -310,7 +319,7 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
||||||
// For nested fields, the parent dsl to search in would shift by one level every iteration
|
// For nested fields, the parent dsl to search in would shift by one level every iteration
|
||||||
Object parent = dsl;
|
Object parent = dsl;
|
||||||
Iterator<String> fieldsIterator = Arrays.stream(fields).filter(fieldToken -> !fieldToken.isBlank()).iterator();
|
Iterator<String> fieldsIterator = Arrays.stream(fields).filter(fieldToken -> !fieldToken.isBlank()).iterator();
|
||||||
Boolean isLeafNode = false;
|
boolean isLeafNode = false;
|
||||||
// This loop will end at either a leaf node, or the last identified JSON field (by throwing an exception)
|
// This loop will end at either a leaf node, or the last identified JSON field (by throwing an exception)
|
||||||
// Valid forms of the fieldPath for this search could be:
|
// Valid forms of the fieldPath for this search could be:
|
||||||
// root.field.list[index].childField.anotherList.indexWithDotOperator.multidimensionalList[index1][index2]
|
// root.field.list[index].childField.anotherList.indexWithDotOperator.multidimensionalList[index1][index2]
|
||||||
|
|
@ -327,30 +336,30 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (IndexOutOfBoundsException e) {
|
||||||
// The index being referred does not exist. Hence the path would not exist.
|
// The index being referred does not exist. Hence the path would not exist.
|
||||||
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
||||||
widgetName, widgetId, fieldPath, pageId, layoutId);
|
widgetName, widgetId, fieldPath, pageId, layoutId, null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
||||||
widgetName, widgetId, fieldPath, pageId, layoutId);
|
widgetName, widgetId, fieldPath, pageId, layoutId, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// After updating the parent, check for the types
|
// After updating the parent, check for the types
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
||||||
widgetName, widgetId, fieldPath, pageId, layoutId);
|
widgetName, widgetId, fieldPath, pageId, layoutId, null);
|
||||||
} else if (parent instanceof String) {
|
} else if (parent instanceof String) {
|
||||||
// If we get String value, then this is a leaf node
|
// If we get String value, then this is a leaf node
|
||||||
isLeafNode = true;
|
isLeafNode = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only extract mustache keys from leaf nodes
|
// Only extract mustache keys from leaf nodes
|
||||||
if (parent != null && isLeafNode) {
|
if (isLeafNode) {
|
||||||
Set<String> mustacheKeysFromFields = MustacheHelper.extractMustacheKeysFromFields(parent);
|
Set<String> mustacheKeysFromFields = MustacheHelper.extractMustacheKeysFromFields(parent);
|
||||||
|
|
||||||
// We found the path. But if the path does not have any mustache bindings, throw the error
|
// We found the path. But if the path does not have any mustache bindings, throw the error
|
||||||
if (mustacheKeysFromFields.isEmpty()) {
|
if (mustacheKeysFromFields.isEmpty()) {
|
||||||
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
throw new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE, widgetType,
|
||||||
widgetName, widgetId, fieldPath, pageId, layoutId);
|
widgetName, widgetId, fieldPath, pageId, layoutId, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamicBindings.addAll(mustacheKeysFromFields);
|
dynamicBindings.addAll(mustacheKeysFromFields);
|
||||||
|
|
@ -499,9 +508,38 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
||||||
.then(Mono.just(pageId));
|
.then(Mono.just(pageId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<Boolean> sendUpdateLayoutAnalyticsEvent(String pageId, String layoutId, JSONObject dsl, boolean isSuccess, Throwable error) {
|
||||||
|
return Mono.zip(
|
||||||
|
sessionUserService.getCurrentUser(),
|
||||||
|
newPageService.getById(pageId)
|
||||||
|
)
|
||||||
|
.flatMap(tuple -> {
|
||||||
|
User t1 = tuple.getT1();
|
||||||
|
NewPage t2 = tuple.getT2();
|
||||||
|
|
||||||
|
final Map<String, Object> data = Map.of(
|
||||||
|
"username", t1.getUsername(),
|
||||||
|
"appId", t2.getApplicationId(),
|
||||||
|
"pageId", pageId,
|
||||||
|
"layoutId", layoutId,
|
||||||
|
"dsl", dsl.toJSONString(),
|
||||||
|
"isSuccessfulExecution", isSuccess,
|
||||||
|
"error", error == null ? "" : error.getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
|
analyticsService.sendEvent(AnalyticsEvents.UPDATE_LAYOUT.getEventName(), t1.getUsername(), data);
|
||||||
|
return Mono.just(isSuccess);
|
||||||
|
})
|
||||||
|
.onErrorResume(e -> {
|
||||||
|
log.warn("Error sending action execution data point", e);
|
||||||
|
return Mono.just(isSuccess);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<LayoutDTO> updateLayout(String pageId, String layoutId, Layout layout) {
|
public Mono<LayoutDTO> updateLayout(String pageId, String layoutId, Layout layout) {
|
||||||
JSONObject dsl = layout.getDsl();
|
final JSONObject dsl = layout.getDsl();
|
||||||
if (dsl == null) {
|
if (dsl == null) {
|
||||||
// There is no DSL here. No need to process anything. Return as is.
|
// There is no DSL here. No need to process anything. Return as is.
|
||||||
return Mono.just(generateResponseDTO(layout));
|
return Mono.just(generateResponseDTO(layout));
|
||||||
|
|
@ -512,7 +550,8 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
||||||
try {
|
try {
|
||||||
extractAllWidgetNamesAndDynamicBindingsFromDSL(dsl, widgetNames, jsSnippetsInDynamicBindings, pageId, layoutId);
|
extractAllWidgetNamesAndDynamicBindingsFromDSL(dsl, widgetNames, jsSnippetsInDynamicBindings, pageId, layoutId);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
return Mono.error(t);
|
return sendUpdateLayoutAnalyticsEvent(pageId, layoutId, dsl, false, t)
|
||||||
|
.then(Mono.error(t));
|
||||||
}
|
}
|
||||||
layout.setWidgetNames(widgetNames);
|
layout.setWidgetNames(widgetNames);
|
||||||
|
|
||||||
|
|
@ -581,11 +620,13 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
||||||
}
|
}
|
||||||
return Mono.empty();
|
return Mono.empty();
|
||||||
})
|
})
|
||||||
.map(savedLayout -> {
|
.flatMap(savedLayout -> {
|
||||||
LayoutDTO layoutDTO = generateResponseDTO(savedLayout);
|
LayoutDTO layoutDTO = generateResponseDTO(savedLayout);
|
||||||
layoutDTO.setActionUpdates(actionUpdates);
|
layoutDTO.setActionUpdates(actionUpdates);
|
||||||
layoutDTO.setMessages(messages);
|
layoutDTO.setMessages(messages);
|
||||||
return layoutDTO;
|
|
||||||
|
return sendUpdateLayoutAnalyticsEvent(pageId, layoutId, dsl, true, null)
|
||||||
|
.thenReturn(layoutDTO);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user