2021-07-08 05:31:08 +00:00
|
|
|
import {
|
|
|
|
|
debuggerLog,
|
|
|
|
|
errorLog,
|
|
|
|
|
logDebuggerErrorAnalytics,
|
|
|
|
|
LogDebuggerErrorAnalyticsPayload,
|
|
|
|
|
updateErrorLog,
|
|
|
|
|
} from "actions/debuggerActions";
|
2021-04-23 13:50:55 +00:00
|
|
|
import { ReduxAction, ReduxActionTypes } from "constants/ReduxActionConstants";
|
2021-06-21 08:20:25 +00:00
|
|
|
import {
|
|
|
|
|
ENTITY_TYPE,
|
|
|
|
|
LogActionPayload,
|
|
|
|
|
Message,
|
|
|
|
|
} from "entities/AppsmithConsole";
|
|
|
|
|
import {
|
|
|
|
|
all,
|
|
|
|
|
call,
|
|
|
|
|
fork,
|
|
|
|
|
put,
|
|
|
|
|
select,
|
|
|
|
|
take,
|
|
|
|
|
takeEvery,
|
|
|
|
|
} from "redux-saga/effects";
|
|
|
|
|
import { get, set } from "lodash";
|
2021-04-23 13:50:55 +00:00
|
|
|
import { getDebuggerErrors } from "selectors/debuggerSelectors";
|
2021-07-08 05:31:08 +00:00
|
|
|
import { getAction, getPlugin } from "selectors/entitiesSelector";
|
2021-04-23 13:50:55 +00:00
|
|
|
import { Action, PluginType } from "entities/Action";
|
|
|
|
|
import LOG_TYPE from "entities/AppsmithConsole/logtype";
|
2021-06-21 08:20:25 +00:00
|
|
|
import { DataTree } from "entities/DataTree/dataTreeFactory";
|
|
|
|
|
import {
|
|
|
|
|
getDataTree,
|
|
|
|
|
getEvaluationInverseDependencyMap,
|
|
|
|
|
} from "selectors/dataTreeSelectors";
|
|
|
|
|
import {
|
|
|
|
|
getEntityNameAndPropertyPath,
|
|
|
|
|
isAction,
|
|
|
|
|
isWidget,
|
|
|
|
|
} from "workers/evaluationUtils";
|
|
|
|
|
import { getDependencyChain } from "components/editorComponents/Debugger/helpers";
|
|
|
|
|
import {
|
|
|
|
|
ACTION_CONFIGURATION_UPDATED,
|
|
|
|
|
createMessage,
|
|
|
|
|
WIDGET_PROPERTIES_UPDATED,
|
|
|
|
|
} from "constants/messages";
|
2021-07-08 05:31:08 +00:00
|
|
|
import AnalyticsUtil from "utils/AnalyticsUtil";
|
|
|
|
|
import { Plugin } from "api/PluginApi";
|
|
|
|
|
import { getCurrentPageId } from "selectors/editorSelectors";
|
|
|
|
|
import { getWidget } from "./selectors";
|
|
|
|
|
import { WidgetProps } from "widgets/BaseWidget";
|
2021-04-23 13:50:55 +00:00
|
|
|
|
|
|
|
|
function* formatActionRequestSaga(payload: LogActionPayload, request?: any) {
|
|
|
|
|
if (!payload.source || !payload.state || !request || !request.headers) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const headers = request.headers;
|
|
|
|
|
|
|
|
|
|
const source = payload.source;
|
|
|
|
|
const action: Action = yield select(getAction, source.id);
|
|
|
|
|
if (action.pluginType === PluginType.API) {
|
|
|
|
|
let formattedHeaders = [];
|
|
|
|
|
|
|
|
|
|
// Convert headers from Record<string, array>[] to Record<string, string>[]
|
|
|
|
|
// for showing in the logs
|
|
|
|
|
formattedHeaders = Object.keys(headers).map((key: string) => {
|
|
|
|
|
const value = headers[key];
|
|
|
|
|
return {
|
|
|
|
|
[key]: value[0],
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return formattedHeaders;
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* onEntityDeleteSaga(payload: Message) {
|
|
|
|
|
const source = payload.source;
|
|
|
|
|
|
|
|
|
|
if (!source) {
|
|
|
|
|
yield put(debuggerLog(payload));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const errors = yield select(getDebuggerErrors);
|
|
|
|
|
const errorIds = Object.keys(errors);
|
|
|
|
|
const updatedErrors: any = {};
|
|
|
|
|
|
|
|
|
|
errorIds.map((e) => {
|
|
|
|
|
const includes = e.includes(source.id);
|
|
|
|
|
|
|
|
|
|
if (!includes) {
|
|
|
|
|
updatedErrors[e] = errors[e];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.DEBUGGER_UPDATE_ERROR_LOGS,
|
|
|
|
|
payload: updatedErrors,
|
|
|
|
|
});
|
|
|
|
|
yield put(debuggerLog(payload));
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-21 08:20:25 +00:00
|
|
|
function* logDependentEntityProperties(payload: Message) {
|
|
|
|
|
const { source, state } = payload;
|
|
|
|
|
if (!state || !source) return;
|
|
|
|
|
|
|
|
|
|
yield take(ReduxActionTypes.SET_EVALUATED_TREE);
|
|
|
|
|
const dataTree: DataTree = yield select(getDataTree);
|
|
|
|
|
|
|
|
|
|
const propertyPath = `${source.name}.` + payload.source?.propertyPath;
|
|
|
|
|
const inverseDependencyMap = yield select(getEvaluationInverseDependencyMap);
|
|
|
|
|
const finalValue = getDependencyChain(propertyPath, inverseDependencyMap);
|
|
|
|
|
|
|
|
|
|
yield all(
|
|
|
|
|
finalValue.map((path) => {
|
|
|
|
|
const entityInfo = getEntityNameAndPropertyPath(path);
|
|
|
|
|
const entity = dataTree[entityInfo.entityName];
|
|
|
|
|
let log = {
|
|
|
|
|
...payload,
|
|
|
|
|
state: {
|
|
|
|
|
[entityInfo.propertyPath]: get(dataTree, path),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (isAction(entity)) {
|
|
|
|
|
log = {
|
|
|
|
|
...log,
|
|
|
|
|
text: createMessage(ACTION_CONFIGURATION_UPDATED),
|
|
|
|
|
source: {
|
|
|
|
|
type: ENTITY_TYPE.ACTION,
|
|
|
|
|
name: entityInfo.entityName,
|
|
|
|
|
id: entity.actionId,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
} else if (isWidget(entity)) {
|
|
|
|
|
log = {
|
|
|
|
|
...log,
|
|
|
|
|
text: createMessage(WIDGET_PROPERTIES_UPDATED),
|
|
|
|
|
source: {
|
|
|
|
|
type: ENTITY_TYPE.WIDGET,
|
|
|
|
|
name: entityInfo.entityName,
|
|
|
|
|
id: entity.widgetId,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return put(debuggerLog(log));
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-23 13:50:55 +00:00
|
|
|
function* debuggerLogSaga(action: ReduxAction<Message>) {
|
|
|
|
|
const { payload } = action;
|
2021-07-08 05:31:08 +00:00
|
|
|
const debuggerErrors: Record<string, Message> = yield select(
|
|
|
|
|
getDebuggerErrors,
|
|
|
|
|
);
|
2021-04-23 13:50:55 +00:00
|
|
|
|
|
|
|
|
switch (payload.logType) {
|
|
|
|
|
case LOG_TYPE.WIDGET_UPDATE:
|
2021-06-04 07:09:36 +00:00
|
|
|
yield put(debuggerLog(payload));
|
2021-06-21 08:20:25 +00:00
|
|
|
yield call(logDependentEntityProperties, payload);
|
2021-06-04 07:09:36 +00:00
|
|
|
return;
|
|
|
|
|
case LOG_TYPE.ACTION_UPDATE:
|
2021-04-23 13:50:55 +00:00
|
|
|
yield put(debuggerLog(payload));
|
2021-06-21 08:20:25 +00:00
|
|
|
yield call(logDependentEntityProperties, payload);
|
2021-04-23 13:50:55 +00:00
|
|
|
return;
|
2021-05-26 12:32:43 +00:00
|
|
|
case LOG_TYPE.EVAL_ERROR:
|
2021-04-23 13:50:55 +00:00
|
|
|
case LOG_TYPE.WIDGET_PROPERTY_VALIDATION_ERROR:
|
|
|
|
|
if (payload.source && payload.source.propertyPath) {
|
|
|
|
|
if (payload.text) {
|
|
|
|
|
yield put(errorLog(payload));
|
2021-05-18 11:51:32 +00:00
|
|
|
|
2021-04-23 13:50:55 +00:00
|
|
|
yield put(debuggerLog(payload));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case LOG_TYPE.ACTION_EXECUTION_ERROR:
|
|
|
|
|
{
|
|
|
|
|
const res = yield call(formatActionRequestSaga, payload, payload.state);
|
|
|
|
|
const log = { ...payload };
|
|
|
|
|
res && set(log, "state.headers", res);
|
2021-07-08 05:31:08 +00:00
|
|
|
if (!((payload.source?.id as string) in debuggerErrors)) {
|
|
|
|
|
yield put(
|
|
|
|
|
logDebuggerErrorAnalytics({
|
|
|
|
|
eventName: "DEBUGGER_NEW_ERROR",
|
|
|
|
|
errorMessages: payload.messages ?? [],
|
|
|
|
|
entityType: ENTITY_TYPE.ACTION,
|
|
|
|
|
entityId: payload.source?.id ?? "",
|
|
|
|
|
entityName: payload.source?.name ?? "",
|
|
|
|
|
propertyPath: "",
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-23 13:50:55 +00:00
|
|
|
yield put(errorLog(log));
|
|
|
|
|
yield put(debuggerLog(log));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case LOG_TYPE.ACTION_EXECUTION_SUCCESS:
|
|
|
|
|
{
|
|
|
|
|
const res = yield call(
|
|
|
|
|
formatActionRequestSaga,
|
|
|
|
|
payload,
|
|
|
|
|
payload.state?.request ?? {},
|
|
|
|
|
);
|
|
|
|
|
|
2021-07-08 05:31:08 +00:00
|
|
|
if ((payload.source?.id as string) in debuggerErrors) {
|
|
|
|
|
yield put(
|
|
|
|
|
logDebuggerErrorAnalytics({
|
|
|
|
|
eventName: "DEBUGGER_RESOLVED_ERROR",
|
|
|
|
|
errorMessages:
|
|
|
|
|
debuggerErrors[payload.source?.id ?? ""].messages ?? [],
|
|
|
|
|
entityType: ENTITY_TYPE.ACTION,
|
|
|
|
|
entityId: payload.source?.id ?? "",
|
|
|
|
|
entityName: payload.source?.name ?? "",
|
|
|
|
|
propertyPath: "",
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-04-23 13:50:55 +00:00
|
|
|
yield put(
|
|
|
|
|
updateErrorLog({
|
|
|
|
|
...payload,
|
|
|
|
|
state: {},
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const log = { ...payload };
|
|
|
|
|
res && set(log, "state.request.headers", res);
|
|
|
|
|
yield put(debuggerLog(log));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case LOG_TYPE.ENTITY_DELETED:
|
|
|
|
|
yield fork(onEntityDeleteSaga, payload);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
yield put(debuggerLog(payload));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-08 05:31:08 +00:00
|
|
|
// This saga is intended for analytics only
|
|
|
|
|
function* logDebuggerErrorAnalyticsSaga(
|
|
|
|
|
action: ReduxAction<LogDebuggerErrorAnalyticsPayload>,
|
|
|
|
|
) {
|
|
|
|
|
const { payload } = action;
|
|
|
|
|
const currentPageId = yield select(getCurrentPageId);
|
|
|
|
|
|
|
|
|
|
if (payload.entityType === ENTITY_TYPE.WIDGET) {
|
|
|
|
|
const widget: WidgetProps = yield select(getWidget, payload.entityId);
|
|
|
|
|
const widgetType = widget.type;
|
|
|
|
|
const propertyPath = `${widgetType}.${payload.propertyPath}`;
|
|
|
|
|
|
|
|
|
|
// Sending widget type for widgets
|
|
|
|
|
AnalyticsUtil.logEvent(payload.eventName, {
|
|
|
|
|
entityType: widgetType,
|
|
|
|
|
propertyPath,
|
|
|
|
|
errorMessages: payload.errorMessages,
|
|
|
|
|
pageId: currentPageId,
|
|
|
|
|
});
|
|
|
|
|
} else if (payload.entityType === ENTITY_TYPE.ACTION) {
|
|
|
|
|
const action: Action = yield select(getAction, payload.entityId);
|
|
|
|
|
const plugin: Plugin = yield select(getPlugin, action.pluginId);
|
|
|
|
|
const pluginName = plugin.name.replace(/ /g, "");
|
|
|
|
|
let propertyPath = `${pluginName}`;
|
|
|
|
|
|
|
|
|
|
if (payload.propertyPath) {
|
|
|
|
|
propertyPath += `.${payload.propertyPath}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sending plugin name for actions
|
|
|
|
|
AnalyticsUtil.logEvent(payload.eventName, {
|
|
|
|
|
entityType: pluginName,
|
|
|
|
|
propertyPath,
|
|
|
|
|
errorMessages: payload.errorMessages,
|
|
|
|
|
pageId: currentPageId,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-23 13:50:55 +00:00
|
|
|
export default function* debuggerSagasListeners() {
|
2021-07-08 05:31:08 +00:00
|
|
|
yield all([
|
|
|
|
|
takeEvery(ReduxActionTypes.DEBUGGER_LOG_INIT, debuggerLogSaga),
|
|
|
|
|
takeEvery(
|
|
|
|
|
ReduxActionTypes.DEBUGGER_ERROR_ANALYTICS,
|
|
|
|
|
logDebuggerErrorAnalyticsSaga,
|
|
|
|
|
),
|
|
|
|
|
]);
|
2021-04-23 13:50:55 +00:00
|
|
|
}
|