fix: improve null safety in action execution analytics data collection (#40905)
## Description Fix NPE in ActionExecutionSolutionCEImpl by replacing `Map.of()` with explicit HashMap entries. This change improves error resilience by adding null checks with default values for all map entries and makes the code more maintainable by separating each property assignment into individual operations. Fixes #40904 ## Automation /ok-to-test tags="@tag.Sanity" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/15552352827> > Commit: 48335f468fb5104ff911f277d121817202ea7545 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15552352827&attempt=2" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Sanity` > Spec: > <hr>Tue, 10 Jun 2025 07:43:44 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Improved handling of missing or null information in analytics event data to ensure more consistent and reliable reporting. No changes to user-facing features or workflows. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
a88ec80bb1
commit
befe9ffd64
|
|
@ -1127,27 +1127,21 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
? ApplicationMode.PUBLISHED.toString()
|
||||
: ApplicationMode.EDIT.toString();
|
||||
|
||||
final Map<String, Object> data = new HashMap<>(Map.of(
|
||||
"username",
|
||||
user.getUsername(),
|
||||
"type",
|
||||
pluginType,
|
||||
"pluginName",
|
||||
plugin.getName(),
|
||||
"name",
|
||||
actionDTO.getName(),
|
||||
"datasource",
|
||||
Map.of("name", datasourceStorage.getName()),
|
||||
"workspaceId",
|
||||
application.getWorkspaceId(),
|
||||
"appId",
|
||||
actionDTO.getApplicationId(),
|
||||
FieldName.APP_MODE,
|
||||
appMode,
|
||||
"appName",
|
||||
application.getName(),
|
||||
"isExampleApp",
|
||||
application.isAppIsExample()));
|
||||
final Map<String, Object> data = new HashMap<>();
|
||||
data.put("username", user.getUsername());
|
||||
data.put("type", pluginType);
|
||||
data.put("pluginName", plugin.getName());
|
||||
data.put("name", actionDTO.getName());
|
||||
|
||||
Map<String, Object> datasourceInfo = new HashMap<>();
|
||||
datasourceInfo.put("name", datasourceStorage.getName());
|
||||
data.put("datasource", datasourceInfo);
|
||||
|
||||
data.put("workspaceId", application.getWorkspaceId());
|
||||
data.put("appId", actionDTO.getApplicationId());
|
||||
data.put(FieldName.APP_MODE, appMode);
|
||||
data.put("appName", application.getName());
|
||||
data.put("isExampleApp", application.isAppIsExample());
|
||||
|
||||
String dsCreatedAt = "";
|
||||
if (datasourceStorage.getCreatedAt() != null) {
|
||||
|
|
@ -1160,37 +1154,28 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
List<String> executionParams =
|
||||
paramsList.stream().map(param -> param.getValue()).collect(Collectors.toList());
|
||||
|
||||
data.putAll(Map.of(
|
||||
"request",
|
||||
request,
|
||||
data.put("request", request);
|
||||
data.put(
|
||||
"isSuccessfulExecution",
|
||||
ObjectUtils.defaultIfNull(actionExecutionResult.getIsExecutionSuccess(), false),
|
||||
"statusCode",
|
||||
ObjectUtils.defaultIfNull(actionExecutionResult.getStatusCode(), ""),
|
||||
"timeElapsed",
|
||||
timeElapsed,
|
||||
"actionCreated",
|
||||
DateUtils.ISO_FORMATTER.format(actionDTO.getCreatedAt()),
|
||||
"actionId",
|
||||
ObjectUtils.defaultIfNull(actionDTO.getId(), "")));
|
||||
data.putAll(Map.of(
|
||||
ObjectUtils.defaultIfNull(actionExecutionResult.getIsExecutionSuccess(), false));
|
||||
data.put("statusCode", ObjectUtils.defaultIfNull(actionExecutionResult.getStatusCode(), ""));
|
||||
data.put("timeElapsed", timeElapsed);
|
||||
data.put("actionCreated", DateUtils.ISO_FORMATTER.format(actionDTO.getCreatedAt()));
|
||||
data.put("actionId", ObjectUtils.defaultIfNull(actionDTO.getId(), ""));
|
||||
data.put(
|
||||
FieldName.ACTION_EXECUTION_REQUEST_PARAMS_SIZE,
|
||||
executeActionDto.getTotalReadableByteCount(),
|
||||
FieldName.ACTION_EXECUTION_REQUEST_PARAMS_COUNT,
|
||||
executionParams.size()));
|
||||
executeActionDto.getTotalReadableByteCount());
|
||||
data.put(FieldName.ACTION_EXECUTION_REQUEST_PARAMS_COUNT, executionParams.size());
|
||||
|
||||
setContextSpecificProperties(data, actionDTO, pageName);
|
||||
|
||||
ActionExecutionResult.PluginErrorDetails pluginErrorDetails =
|
||||
actionExecutionResult.getPluginErrorDetails();
|
||||
|
||||
data.putAll(Map.of("pluginErrorDetails", ObjectUtils.defaultIfNull(pluginErrorDetails, "")));
|
||||
|
||||
data.put("pluginErrorDetails", ObjectUtils.defaultIfNull(pluginErrorDetails, ""));
|
||||
if (pluginErrorDetails != null) {
|
||||
data.putAll(Map.of(
|
||||
"appsmithErrorCode", pluginErrorDetails.getAppsmithErrorCode(),
|
||||
"appsmithErrorMessage", pluginErrorDetails.getAppsmithErrorMessage(),
|
||||
"errorType", pluginErrorDetails.getErrorType()));
|
||||
data.put("appsmithErrorCode", pluginErrorDetails.getAppsmithErrorCode());
|
||||
data.put("appsmithErrorMessage", pluginErrorDetails.getAppsmithErrorMessage());
|
||||
data.put("errorType", pluginErrorDetails.getErrorType());
|
||||
}
|
||||
|
||||
data.putAll(DatasourceAnalyticsUtils.getAnalyticsPropertiesWithStorageOnActionExecution(
|
||||
|
|
@ -1219,15 +1204,15 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
actionExecutionResult.getRequest().getQuery();
|
||||
}
|
||||
|
||||
final Map<String, Object> eventData = new HashMap<>(Map.of(
|
||||
FieldName.ACTION, actionDTO,
|
||||
FieldName.DATASOURCE, datasourceStorage,
|
||||
FieldName.APP_MODE, appMode,
|
||||
FieldName.ACTION_EXECUTION_RESULT, actionExecutionResult,
|
||||
FieldName.ACTION_EXECUTION_TIME, timeElapsed,
|
||||
FieldName.ACTION_EXECUTION_QUERY, executionRequestQuery,
|
||||
FieldName.APPLICATION, application,
|
||||
FieldName.PLUGIN, plugin));
|
||||
final Map<String, Object> eventData = new HashMap<>();
|
||||
eventData.put(FieldName.ACTION, actionDTO);
|
||||
eventData.put(FieldName.DATASOURCE, datasourceStorage);
|
||||
eventData.put(FieldName.APP_MODE, appMode);
|
||||
eventData.put(FieldName.ACTION_EXECUTION_RESULT, actionExecutionResult);
|
||||
eventData.put(FieldName.ACTION_EXECUTION_TIME, timeElapsed);
|
||||
eventData.put(FieldName.ACTION_EXECUTION_QUERY, executionRequestQuery);
|
||||
eventData.put(FieldName.APPLICATION, application);
|
||||
eventData.put(FieldName.PLUGIN, plugin);
|
||||
|
||||
if (executeActionDto.getTotalReadableByteCount() <= Constraint.MAX_ANALYTICS_SIZE_BYTES) {
|
||||
// Only send params info if total size is less than 5 MB
|
||||
|
|
@ -1259,7 +1244,8 @@ public class ActionExecutionSolutionCEImpl implements ActionExecutionSolutionCE
|
|||
}
|
||||
|
||||
protected void setContextSpecificProperties(Map<String, Object> data, ActionDTO actionDTO, String contextName) {
|
||||
data.putAll(Map.of("pageId", ObjectUtils.defaultIfNull(actionDTO.getPageId(), ""), "pageName", contextName));
|
||||
data.put("pageId", ObjectUtils.defaultIfNull(actionDTO.getPageId(), ""));
|
||||
data.put("pageName", ObjectUtils.defaultIfNull(contextName, ""));
|
||||
}
|
||||
|
||||
protected Mono<ActionDTO> setAutoGeneratedHeaders(Plugin plugin, ActionDTO actionDTO, HttpHeaders httpHeaders) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user