Feature/instrumentation (#744)
* bumped sentry version modified performance monitor to use a queue internally to make synchronous logging easy added logging for api pane close / open and various different methods * added use effect to stop tracking on mount of entity properties * removed open api tracking * fixed stop tracking to pop from the end instead of the beginning added tracking for editor mount and sidebar mount * added tracking for entity explorer * moved from app route to sentry app route because passing JSX to app route causes re-renders * Fixing theme and route change issues. * added performance tracking for API / Query execution and Page Load actions * added isntrumentation to open / close actions * added instrumentation for apis & actions * reduced sample rate added async tracking * added tracking for property pane * Remove tracking from reducer * added option to attach async operations to parent transactions * Fix typo Co-authored-by: Nikhil Nandagopal <nikhil@appsmith.com> Co-authored-by: Satbir Singh <satbir121@gmail.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com>
This commit is contained in:
parent
dc1e2e124f
commit
3fdd0a246a
|
|
@ -192,6 +192,7 @@ export const executeApiActionRequest = (payload: { id: string }) => ({
|
|||
export const executeApiActionSuccess = (payload: {
|
||||
id: string;
|
||||
response: ActionResponse;
|
||||
isPageLoad?: boolean;
|
||||
}) => ({
|
||||
type: ReduxActionTypes.EXECUTE_API_ACTION_SUCCESS,
|
||||
payload: payload,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ import {
|
|||
PageAction,
|
||||
} from "constants/ActionConstants";
|
||||
import { BatchAction, batchAction } from "actions/batchActions";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
||||
export const executeAction = (
|
||||
payload: ExecuteActionPayload,
|
||||
|
|
@ -79,6 +82,9 @@ export const closeAllModals = () => {
|
|||
};
|
||||
|
||||
export const forceOpenPropertyPane = (id: string) => {
|
||||
PerformanceTracker.startTracking(
|
||||
PerformanceTransactionName.OPEN_PROPERTY_PANE,
|
||||
);
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_PROPERTY_PANE,
|
||||
payload: {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ import {
|
|||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import HelpControl from "./HelpControl";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
||||
const PositionStyle = styled.div`
|
||||
position: absolute;
|
||||
|
|
@ -68,6 +71,9 @@ export const WidgetNameComponent = (props: WidgetNameComponentProps) => {
|
|||
props.widgetId === propertyPaneState.widgetId) ||
|
||||
props.widgetId !== propertyPaneState.widgetId
|
||||
) {
|
||||
PerformanceTracker.startTracking(
|
||||
PerformanceTransactionName.OPEN_PROPERTY_PANE,
|
||||
);
|
||||
AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN_CLICK", {
|
||||
widgetType: props.type,
|
||||
widgetId: props.widgetId,
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => {
|
|||
routingInstrumentation: Sentry.reactRouterV5Instrumentation(history),
|
||||
}),
|
||||
],
|
||||
tracesSampleRate: 1.0,
|
||||
tracesSampleRate: 0.5,
|
||||
},
|
||||
smartLook: {
|
||||
enabled: smartLook.enabled,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ export interface PageAction {
|
|||
export interface ExecuteErrorPayload {
|
||||
actionId: string;
|
||||
error: any;
|
||||
isPageLoad?: boolean;
|
||||
}
|
||||
|
||||
// Group 1 = datasource (https://www.domain.com)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ import {
|
|||
getCurrentPageName,
|
||||
} from "selectors/editorSelectors";
|
||||
import ConfirmRunModal from "pages/Editor/ConfirmRunModal";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
||||
const Section = styled.section`
|
||||
background: ${props => props.theme.colors.bodyBG};
|
||||
|
|
@ -112,15 +109,11 @@ class AppViewerPageContainer extends Component<AppViewerPageContainerProps> {
|
|||
}
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
PerformanceTracker.startTracking(
|
||||
PerformanceTransactionName.GENERATE_VIEW_MODE_PROPS,
|
||||
);
|
||||
const props = {
|
||||
isFetchingPage: getIsFetchingPage(state),
|
||||
widgets: getCanvasWidgetDsl(state),
|
||||
currentPageName: getCurrentPageName(state),
|
||||
};
|
||||
PerformanceTracker.stopTracking();
|
||||
return props;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ const LoadingContainer = styled(CenteredWrapper)`
|
|||
|
||||
interface ReduxStateProps {
|
||||
actions: ActionDataState;
|
||||
isRunning: Record<string, boolean>;
|
||||
isDeleting: Record<string, boolean>;
|
||||
isRunning: boolean;
|
||||
isDeleting: boolean;
|
||||
isCreating: boolean;
|
||||
apiName: string;
|
||||
currentApplication: UserApplication;
|
||||
|
|
@ -71,6 +71,9 @@ type Props = ReduxActionProps &
|
|||
|
||||
class ApiEditor extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
PerformanceTracker.stopTracking(PerformanceTransactionName.OPEN_ACTION, {
|
||||
actionType: "API",
|
||||
});
|
||||
this.props.changeAPIPage(this.props.match.params.apiId);
|
||||
}
|
||||
handleDeleteClick = () => {
|
||||
|
|
@ -87,6 +90,9 @@ class ApiEditor extends React.Component<Props> {
|
|||
};
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
if (prevProps.isRunning === true && this.props.isRunning === false) {
|
||||
PerformanceTracker.stopTracking(PerformanceTransactionName.RUN_API_CLICK);
|
||||
}
|
||||
if (prevProps.match.params.apiId !== this.props.match.params.apiId) {
|
||||
this.props.changeAPIPage(this.props.match.params.apiId);
|
||||
}
|
||||
|
|
@ -97,6 +103,9 @@ class ApiEditor extends React.Component<Props> {
|
|||
this.props.pages,
|
||||
this.props.match.params.pageId,
|
||||
);
|
||||
PerformanceTracker.startTracking(PerformanceTransactionName.RUN_API_CLICK, {
|
||||
apiId: this.props.match.params.apiId,
|
||||
});
|
||||
AnalyticsUtil.logEvent("RUN_API_CLICK", {
|
||||
apiName: this.props.apiName,
|
||||
apiID: this.props.match.params.apiId,
|
||||
|
|
@ -174,8 +183,8 @@ class ApiEditor extends React.Component<Props> {
|
|||
<ApiEditorForm
|
||||
pluginId={pluginId}
|
||||
paginationType={paginationType}
|
||||
isRunning={isRunning[apiId]}
|
||||
isDeleting={isDeleting[apiId]}
|
||||
isRunning={isRunning}
|
||||
isDeleting={isDeleting}
|
||||
onDeleteClick={this.handleDeleteClick}
|
||||
onRunClick={this.handleRunClick}
|
||||
appName={
|
||||
|
|
@ -192,8 +201,8 @@ class ApiEditor extends React.Component<Props> {
|
|||
apiName={this.props.apiName}
|
||||
apiId={this.props.match.params.apiId}
|
||||
paginationType={paginationType}
|
||||
isRunning={isRunning[apiId]}
|
||||
isDeleting={isDeleting[apiId]}
|
||||
isRunning={isRunning}
|
||||
isDeleting={isDeleting}
|
||||
onDeleteClick={this.handleDeleteClick}
|
||||
onRunClick={this.handleRunClick}
|
||||
appName={
|
||||
|
|
@ -217,9 +226,6 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
|
|||
const apiAction = getActionById(state, props);
|
||||
const apiName = getApiName(state, props.match.params.apiId);
|
||||
const { isDeleting, isRunning, isCreating } = state.ui.apiPane;
|
||||
PerformanceTracker.startTracking(
|
||||
PerformanceTransactionName.GENERATE_API_PROPS,
|
||||
);
|
||||
const apiEditorState = {
|
||||
actions: state.entities.actions,
|
||||
currentApplication: getCurrentApplication(state),
|
||||
|
|
@ -230,12 +236,11 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
|
|||
pluginId: _.get(apiAction, "pluginId"),
|
||||
paginationType: _.get(apiAction, "actionConfiguration.paginationType"),
|
||||
apiAction,
|
||||
isRunning,
|
||||
isDeleting,
|
||||
isCreating,
|
||||
isRunning: isRunning[props.match.params.apiId],
|
||||
isDeleting: isDeleting[props.match.params.apiId],
|
||||
isCreating: isCreating,
|
||||
isEditorInitialized: getIsEditorInitialized(state),
|
||||
};
|
||||
PerformanceTracker.stopTracking();
|
||||
return apiEditorState;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ import EntityProperties from "../Entity/EntityProperties";
|
|||
import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
|
||||
import { ExplorerURLParams } from "../helpers";
|
||||
import { useParams } from "react-router";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
||||
const getUpdateActionNameReduxAction = (id: string, name: string) => {
|
||||
return saveActionName({ id, name });
|
||||
|
|
@ -25,6 +28,9 @@ type ExplorerActionEntityProps = {
|
|||
export const ExplorerActionEntity = memo((props: ExplorerActionEntityProps) => {
|
||||
const { pageId } = useParams<ExplorerURLParams>();
|
||||
const switchToAction = useCallback(() => {
|
||||
PerformanceTracker.startTracking(PerformanceTransactionName.OPEN_ACTION, {
|
||||
url: props.url,
|
||||
});
|
||||
props.url && history.push(props.url);
|
||||
}, [props.url]);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ export const EntityProperties = (props: {
|
|||
PerformanceTransactionName.ENTITY_EXPLORER_ENTITY,
|
||||
);
|
||||
useEffect(() => {
|
||||
PerformanceTracker.stopTracking();
|
||||
PerformanceTracker.stopTracking(
|
||||
PerformanceTransactionName.ENTITY_EXPLORER_ENTITY,
|
||||
);
|
||||
});
|
||||
let entity: any;
|
||||
const dataTree: DataTree = useSelector(evaluateDataTreeWithoutFunctions);
|
||||
|
|
|
|||
|
|
@ -175,11 +175,20 @@ class PropertyPane extends Component<
|
|||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
PerformanceTracker.stopTracking(
|
||||
PerformanceTransactionName.OPEN_PROPERTY_PANE,
|
||||
);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: PropertyPaneProps & PropertyPaneFunctions) {
|
||||
if (
|
||||
this.props.widgetId !== prevProps.widgetId &&
|
||||
this.props.widgetId !== undefined
|
||||
) {
|
||||
PerformanceTracker.stopTracking(
|
||||
PerformanceTransactionName.OPEN_PROPERTY_PANE,
|
||||
);
|
||||
if (prevProps.widgetId && prevProps.widgetProperties) {
|
||||
AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE", {
|
||||
widgetType: prevProps.widgetProperties.type,
|
||||
|
|
@ -227,16 +236,12 @@ class PropertyPane extends Component<
|
|||
}
|
||||
|
||||
const mapStateToProps = (state: AppState): PropertyPaneProps => {
|
||||
PerformanceTracker.startTracking(
|
||||
PerformanceTransactionName.GENERATE_PROPERTY_PANE_PROPS,
|
||||
);
|
||||
const props = {
|
||||
propertySections: getPropertyConfig(state),
|
||||
widgetId: getCurrentWidgetId(state),
|
||||
widgetProperties: getWidgetPropsForPropertyPane(state),
|
||||
isVisible: getIsPropertyPaneVisible(state),
|
||||
};
|
||||
PerformanceTracker.stopTracking();
|
||||
return props;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import { getIsEditorInitialized } from "selectors/editorSelectors";
|
|||
import { QUERY_EDITOR_FORM_NAME } from "constants/forms";
|
||||
import { Plugin } from "api/PluginApi";
|
||||
import { Datasource } from "api/DatasourcesApi";
|
||||
import { QueryPaneReduxState } from "reducers/uiReducers/queryPaneReducer";
|
||||
import {
|
||||
getPluginIdsOfPackageNames,
|
||||
getPlugins,
|
||||
|
|
@ -26,6 +25,10 @@ import { QueryAction } from "entities/Action";
|
|||
import Spinner from "components/editorComponents/Spinner";
|
||||
import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper";
|
||||
import { changeQuery } from "actions/queryPaneActions";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
const EmptyStateContainer = styled.div`
|
||||
display: flex;
|
||||
|
|
@ -46,7 +49,8 @@ type ReduxDispatchProps = {
|
|||
type ReduxStateProps = {
|
||||
plugins: Plugin[];
|
||||
dataSources: Datasource[];
|
||||
queryPane: QueryPaneReduxState;
|
||||
isRunning: boolean;
|
||||
isDeleting: boolean;
|
||||
formData: QueryAction;
|
||||
runErrorMessage: Record<string, string>;
|
||||
pluginIds: Array<string> | undefined;
|
||||
|
|
@ -65,6 +69,9 @@ type Props = StateAndRouteProps & ReduxDispatchProps & ReduxStateProps;
|
|||
class QueryEditor extends React.Component<Props> {
|
||||
componentDidMount() {
|
||||
this.props.changeQueryPage(this.props.match.params.queryId);
|
||||
PerformanceTracker.stopTracking(PerformanceTransactionName.OPEN_ACTION, {
|
||||
actionType: "QUERY",
|
||||
});
|
||||
}
|
||||
handleDeleteClick = () => {
|
||||
const { queryId } = this.props.match.params;
|
||||
|
|
@ -74,10 +81,22 @@ class QueryEditor extends React.Component<Props> {
|
|||
|
||||
handleRunClick = () => {
|
||||
const { match } = this.props;
|
||||
PerformanceTracker.startTracking(
|
||||
PerformanceTransactionName.RUN_QUERY_CLICK,
|
||||
{ queryId: this.props.match.params.queryId },
|
||||
);
|
||||
AnalyticsUtil.logEvent("RUN_QUERY_CLICK", {
|
||||
queryId: this.props.match.params.queryId,
|
||||
});
|
||||
this.props.runAction(match.params.queryId);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
if (prevProps.isRunning === true && this.props.isRunning === false) {
|
||||
PerformanceTracker.stopTracking(
|
||||
PerformanceTransactionName.RUN_QUERY_CLICK,
|
||||
);
|
||||
}
|
||||
if (prevProps.match.params.queryId !== this.props.match.params.queryId) {
|
||||
this.props.changeQueryPage(this.props.match.params.queryId);
|
||||
}
|
||||
|
|
@ -86,7 +105,8 @@ class QueryEditor extends React.Component<Props> {
|
|||
render() {
|
||||
const {
|
||||
dataSources,
|
||||
queryPane,
|
||||
isRunning,
|
||||
isDeleting,
|
||||
match: {
|
||||
params: { queryId },
|
||||
},
|
||||
|
|
@ -114,7 +134,6 @@ class QueryEditor extends React.Component<Props> {
|
|||
</LoadingContainer>
|
||||
);
|
||||
}
|
||||
const { isRunning, isDeleting } = queryPane;
|
||||
|
||||
const DATASOURCES_OPTIONS = dataSources.map(dataSource => ({
|
||||
label: dataSource.name,
|
||||
|
|
@ -128,8 +147,8 @@ class QueryEditor extends React.Component<Props> {
|
|||
location={this.props.location}
|
||||
applicationId={applicationId}
|
||||
pageId={pageId}
|
||||
isRunning={isRunning[queryId]}
|
||||
isDeleting={isDeleting[queryId]}
|
||||
isRunning={isRunning}
|
||||
isDeleting={isDeleting}
|
||||
onDeleteClick={this.handleDeleteClick}
|
||||
onRunClick={this.handleRunClick}
|
||||
dataSources={dataSources}
|
||||
|
|
@ -175,7 +194,8 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
|
|||
pluginIds: getPluginIdsOfPackageNames(state, PLUGIN_PACKAGE_DBS),
|
||||
dataSources: getDBDatasources(state),
|
||||
responses: getActionResponses(state),
|
||||
queryPane: state.ui.queryPane,
|
||||
isRunning: state.ui.queryPane.isRunning[props.match.params.queryId],
|
||||
isDeleting: state.ui.queryPane.isDeleting[props.match.params.queryId],
|
||||
formData,
|
||||
editorConfig,
|
||||
loadingFormConfigs,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ const WidgetsEditor = () => {
|
|||
|
||||
useEffect(() => {
|
||||
PerformanceTracker.stopTracking(PerformanceTransactionName.EDITOR_MOUNT);
|
||||
PerformanceTracker.stopTracking(PerformanceTransactionName.CLOSE_API);
|
||||
PerformanceTracker.stopTracking(PerformanceTransactionName.CLOSE_SIDE_PANE);
|
||||
});
|
||||
|
||||
// Switch page
|
||||
|
|
|
|||
|
|
@ -88,7 +88,10 @@ class EditorsRouter extends React.Component<
|
|||
}
|
||||
|
||||
handleClose = (e: React.MouseEvent) => {
|
||||
PerformanceTracker.startTracking(PerformanceTransactionName.CLOSE_API);
|
||||
PerformanceTracker.startTracking(
|
||||
PerformanceTransactionName.CLOSE_SIDE_PANE,
|
||||
{ path: this.props.location.pathname },
|
||||
);
|
||||
e.stopPropagation();
|
||||
const { applicationId, pageId } = this.props.match.params;
|
||||
this.setState({
|
||||
|
|
|
|||
|
|
@ -66,9 +66,14 @@ const editorReducer = createReducer(initialState, {
|
|||
[ReduxActionErrorTypes.INITIALIZE_EDITOR_ERROR]: (
|
||||
state: EditorReduxState,
|
||||
) => {
|
||||
state.loadingStates.loading = false;
|
||||
state.loadingStates.loadingError = true;
|
||||
return { ...state };
|
||||
return {
|
||||
...state,
|
||||
loadingStates: {
|
||||
...state.loadingStates,
|
||||
loading: false,
|
||||
loadingError: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.PUBLISH_APPLICATION_INIT]: (state: EditorReduxState) => {
|
||||
state.loadingStates.publishing = true;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ import { updateAppStore } from "actions/pageActions";
|
|||
import { getAppStoreName } from "constants/AppConstants";
|
||||
import downloadjs from "downloadjs";
|
||||
import { getType, Types } from "utils/TypeHelpers";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
||||
function* navigateActionSaga(
|
||||
action: { pageNameOrUrl: string; params: Record<string, string> },
|
||||
|
|
@ -283,6 +286,13 @@ export function* executeActionSaga(
|
|||
event: ExecuteActionPayloadEvent,
|
||||
) {
|
||||
const { actionId, onSuccess, onError, params } = apiAction;
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_ACTION,
|
||||
{
|
||||
actionId: actionId,
|
||||
},
|
||||
actionId,
|
||||
);
|
||||
try {
|
||||
const api: RestAction = yield select(getAction, actionId);
|
||||
|
||||
|
|
@ -326,6 +336,11 @@ export function* executeActionSaga(
|
|||
}),
|
||||
);
|
||||
if (isErrorResponse(response)) {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_ACTION,
|
||||
{ failed: true },
|
||||
actionId,
|
||||
);
|
||||
if (onError) {
|
||||
yield put(
|
||||
executeAction({
|
||||
|
|
@ -348,6 +363,11 @@ export function* executeActionSaga(
|
|||
type: "error",
|
||||
});
|
||||
} else {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_ACTION,
|
||||
undefined,
|
||||
actionId,
|
||||
);
|
||||
if (onSuccess) {
|
||||
yield put(
|
||||
executeAction({
|
||||
|
|
@ -579,6 +599,14 @@ function* confirmRunActionSaga() {
|
|||
}
|
||||
|
||||
function* executePageLoadAction(pageAction: PageAction) {
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_ACTION,
|
||||
{
|
||||
actionId: pageAction.id,
|
||||
},
|
||||
pageAction.id,
|
||||
PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
|
||||
);
|
||||
yield put(executeApiActionRequest({ id: pageAction.id }));
|
||||
const params: Property[] = yield call(
|
||||
getActionParams,
|
||||
|
|
@ -592,20 +620,33 @@ function* executePageLoadAction(pageAction: PageAction) {
|
|||
executeActionRequest,
|
||||
pageAction.timeoutInMillisecond,
|
||||
);
|
||||
|
||||
if (isErrorResponse(response)) {
|
||||
yield put(
|
||||
executeActionError({
|
||||
actionId: pageAction.id,
|
||||
error: response.responseMeta.error,
|
||||
isPageLoad: true,
|
||||
}),
|
||||
);
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_ACTION,
|
||||
{
|
||||
failed: true,
|
||||
},
|
||||
pageAction.id,
|
||||
);
|
||||
} else {
|
||||
const payload = createActionExecutionResponse(response);
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_ACTION,
|
||||
undefined,
|
||||
pageAction.id,
|
||||
);
|
||||
yield put(
|
||||
executeApiActionSuccess({
|
||||
id: pageAction.id,
|
||||
response: payload,
|
||||
isPageLoad: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
@ -613,10 +654,20 @@ function* executePageLoadAction(pageAction: PageAction) {
|
|||
|
||||
function* executePageLoadActionsSaga(action: ReduxAction<PageAction[][]>) {
|
||||
const pageActions = action.payload;
|
||||
const actionCount = _.flatten(pageActions).length;
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
|
||||
{ numActions: actionCount },
|
||||
);
|
||||
for (const actionSet of pageActions) {
|
||||
// Load all sets in parallel
|
||||
yield* yield all(actionSet.map(a => call(executePageLoadAction, a)));
|
||||
yield* yield all(
|
||||
actionSet.map(apiAction => call(executePageLoadAction, apiAction)),
|
||||
);
|
||||
}
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
|
||||
);
|
||||
}
|
||||
|
||||
export function* watchActionExecutionSagas() {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ import {
|
|||
QUERIES_EDITOR_ID_URL,
|
||||
API_EDITOR_ID_URL,
|
||||
} from "constants/routes";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
||||
export function* createActionSaga(actionPayload: ReduxAction<RestAction>) {
|
||||
try {
|
||||
|
|
@ -94,8 +97,12 @@ export function* createActionSaga(actionPayload: ReduxAction<RestAction>) {
|
|||
}
|
||||
|
||||
export function* fetchActionsSaga(action: ReduxAction<FetchActionsPayload>) {
|
||||
const { applicationId } = action.payload;
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_ACTIONS_API,
|
||||
{ mode: "EDITOR", appId: applicationId },
|
||||
);
|
||||
try {
|
||||
const { applicationId } = action.payload;
|
||||
const response: GenericApiResponse<RestAction[]> = yield ActionAPI.fetchActions(
|
||||
applicationId,
|
||||
);
|
||||
|
|
@ -105,20 +112,31 @@ export function* fetchActionsSaga(action: ReduxAction<FetchActionsPayload>) {
|
|||
type: ReduxActionTypes.FETCH_ACTIONS_SUCCESS,
|
||||
payload: response.data,
|
||||
});
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_ACTIONS_API,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_ACTIONS_ERROR,
|
||||
payload: { error },
|
||||
});
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_ACTIONS_API,
|
||||
{ failed: true },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function* fetchActionsForViewModeSaga(
|
||||
action: ReduxAction<FetchActionsPayload>,
|
||||
) {
|
||||
const { applicationId } = action.payload;
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_ACTIONS_API,
|
||||
{ mode: "VIEWER", appId: applicationId },
|
||||
);
|
||||
try {
|
||||
const { applicationId } = action.payload;
|
||||
const response: GenericApiResponse<RestAction[]> = yield ActionAPI.fetchActionsForViewMode(
|
||||
applicationId,
|
||||
);
|
||||
|
|
@ -128,20 +146,31 @@ export function* fetchActionsForViewModeSaga(
|
|||
type: ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS,
|
||||
payload: response.data,
|
||||
});
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_ACTIONS_API,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR,
|
||||
payload: { error },
|
||||
});
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_ACTIONS_API,
|
||||
{ failed: true },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function* fetchActionsForPageSaga(
|
||||
action: ReduxAction<{ pageId: string }>,
|
||||
) {
|
||||
const { pageId } = action.payload;
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
|
||||
{ pageId: pageId },
|
||||
);
|
||||
try {
|
||||
const { pageId } = action.payload;
|
||||
const response: GenericApiResponse<RestAction[]> = yield call(
|
||||
ActionAPI.fetchActionsByPageId,
|
||||
pageId,
|
||||
|
|
@ -149,8 +178,15 @@ export function* fetchActionsForPageSaga(
|
|||
const isValidResponse = yield validateResponse(response);
|
||||
if (isValidResponse) {
|
||||
yield put(fetchActionsForPageSuccess(response.data));
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
|
||||
{ failed: true },
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_ACTIONS_FOR_PAGE_ERROR,
|
||||
payload: { error },
|
||||
|
|
@ -160,6 +196,10 @@ export function* fetchActionsForPageSaga(
|
|||
|
||||
export function* updateActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
||||
try {
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.UPDATE_ACTION_API,
|
||||
{ actionid: actionPayload.payload.id },
|
||||
);
|
||||
let action: Action = yield select(getAction, actionPayload.payload.id);
|
||||
const isApi = action.pluginType === "API";
|
||||
const isDB = action.pluginType === "DB";
|
||||
|
|
@ -193,10 +233,16 @@ export function* updateActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
|||
pageName: pageName,
|
||||
});
|
||||
}
|
||||
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.UPDATE_ACTION_API,
|
||||
);
|
||||
yield put(updateActionSuccess({ data: response.data }));
|
||||
}
|
||||
} catch (error) {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.UPDATE_ACTION_API,
|
||||
{ failed: true },
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.UPDATE_ACTION_ERROR,
|
||||
payload: { error, id: actionPayload.payload.id },
|
||||
|
|
@ -350,6 +396,10 @@ export function* refactorActionName(
|
|||
newName: string,
|
||||
) {
|
||||
// fetch page of the action
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.REFACTOR_ACTION_NAME,
|
||||
{ actionId: id },
|
||||
);
|
||||
const pageResponse = yield call(PageApi.fetchPage, {
|
||||
id: pageId,
|
||||
});
|
||||
|
|
@ -369,6 +419,11 @@ export function* refactorActionName(
|
|||
const isRefactorSuccessful = yield validateResponse(refactorResponse);
|
||||
|
||||
const currentPageId = yield select(getCurrentPageId);
|
||||
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.REFACTOR_ACTION_NAME,
|
||||
{ isSuccess: isRefactorSuccessful },
|
||||
);
|
||||
if (isRefactorSuccessful) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.SAVE_ACTION_NAME_SUCCESS,
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ import {
|
|||
import { clearCaches } from "utils/DynamicBindingUtils";
|
||||
import { UrlDataState } from "reducers/entityReducers/appReducer";
|
||||
import { getQueryParams } from "utils/AppsmithUtils";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
||||
const getWidgetName = (state: AppState, widgetId: string) =>
|
||||
state.entities.canvasWidgets[widgetId];
|
||||
|
|
@ -79,6 +82,9 @@ const getWidgetName = (state: AppState, widgetId: string) =>
|
|||
export function* fetchPageListSaga(
|
||||
fetchPageListAction: ReduxAction<FetchPageListPayload>,
|
||||
) {
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_LIST_API,
|
||||
);
|
||||
try {
|
||||
const { applicationId } = fetchPageListAction.payload;
|
||||
const response: FetchPageListResponse = yield call(
|
||||
|
|
@ -106,8 +112,15 @@ export function* fetchPageListSaga(
|
|||
applicationId,
|
||||
},
|
||||
});
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_LIST_API,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_LIST_API,
|
||||
{ failed: true },
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_PAGE_LIST_ERROR,
|
||||
payload: {
|
||||
|
|
@ -139,6 +152,10 @@ export function* fetchPageSaga(
|
|||
) {
|
||||
try {
|
||||
const { id } = pageRequestAction.payload;
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_API,
|
||||
{ pageId: id },
|
||||
);
|
||||
const fetchPageResponse: FetchPageResponse = yield call(PageApi.fetchPage, {
|
||||
id,
|
||||
});
|
||||
|
|
@ -167,9 +184,18 @@ export function* fetchPageSaga(
|
|||
dsl: extractCurrentDSL(fetchPageResponse),
|
||||
},
|
||||
});
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_API,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_API,
|
||||
{
|
||||
failed: true,
|
||||
},
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_PAGE_ERROR,
|
||||
payload: {
|
||||
|
|
@ -184,6 +210,10 @@ export function* fetchPublishedPageSaga(
|
|||
) {
|
||||
try {
|
||||
const { pageId, bustCache } = pageRequestAction.payload;
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_API,
|
||||
{ pageId: pageId, published: true },
|
||||
);
|
||||
const request: FetchPublishedPageRequest = {
|
||||
pageId,
|
||||
bustCache,
|
||||
|
|
@ -213,9 +243,18 @@ export function* fetchPublishedPageSaga(
|
|||
}),
|
||||
);
|
||||
// Execute page load actions
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_API,
|
||||
);
|
||||
yield put(executePageLoadActions(canvasWidgetsPayload.pageActions));
|
||||
}
|
||||
} catch (error) {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.FETCH_PAGE_API,
|
||||
{
|
||||
failed: true,
|
||||
},
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_PUBLISHED_PAGE_ERROR,
|
||||
payload: {
|
||||
|
|
@ -242,6 +281,12 @@ function* savePageSaga() {
|
|||
const widgets = yield select(getWidgets);
|
||||
const editorConfigs = yield select(getEditorConfigs) as any;
|
||||
const savePageRequest = getLayoutSavePayload(widgets, editorConfigs);
|
||||
PerformanceTracker.startAsyncTracking(
|
||||
PerformanceTransactionName.SAVE_PAGE_API,
|
||||
{
|
||||
pageId: savePageRequest.pageId,
|
||||
},
|
||||
);
|
||||
try {
|
||||
// Store the updated DSL in the pageDSLs reducer
|
||||
yield put({
|
||||
|
|
@ -266,8 +311,17 @@ function* savePageSaga() {
|
|||
}
|
||||
}
|
||||
yield put(savePageSuccess(savePageResponse));
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.SAVE_PAGE_API,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
PerformanceTracker.stopAsyncTracking(
|
||||
PerformanceTransactionName.SAVE_PAGE_API,
|
||||
{
|
||||
failed: true,
|
||||
},
|
||||
);
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.SAVE_PAGE_ERROR,
|
||||
payload: {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ export type EventName =
|
|||
| "DUPLICATE_API"
|
||||
| "DUPLICATE_API_CLICK"
|
||||
| "RUN_QUERY"
|
||||
| "RUN_QUERY_CLICK"
|
||||
| "DELETE_QUERY"
|
||||
| "SAVE_QUERY"
|
||||
| "MOVE_API"
|
||||
|
|
|
|||
|
|
@ -5,13 +5,6 @@ import * as log from "loglevel";
|
|||
|
||||
export enum PerformanceTransactionName {
|
||||
DEPLOY_APPLICATION = "DEPLOY_APPLICATION",
|
||||
RUN_ACTION = "RUN_ACTION",
|
||||
PAGE_SWITCH_EDIT = "PAGE_SWITCH_EDIT",
|
||||
PAGE_SWITCH_VIEW = "PAGE_SWITCH_VIEW",
|
||||
CREATE_ACTION = "CREATE_ACTION",
|
||||
CURL_IMPORT = "CURL_IMPORT",
|
||||
EXECUTE_WIDGET_ACTION = "EXECUTE_WIDGET_ACTION",
|
||||
RUN_ACTION_WAIT_FOR_SAVE = "RUN_ACTION_WAIT_FOR_SAVE",
|
||||
DATA_TREE_EVALUATION = "DATA_TREE_EVALUATION",
|
||||
CONSTRUCT_UNEVAL_TREE = "CONSTRUCT_UNEVAL_TREE",
|
||||
CONSTRUCT_CANVAS_DSL = "CONSTRUCT_CANVAS_DSL",
|
||||
|
|
@ -20,22 +13,27 @@ export enum PerformanceTransactionName {
|
|||
SET_WIDGET_LOADING = "SET_WIDGET_LOADING",
|
||||
VALIDATE_DATA_TREE = "VALIDATE_DATA_TREE",
|
||||
EXECUTE_PAGE_LOAD_ACTIONS = "EXECUTE_PAGE_LOAD_ACTIONS",
|
||||
SAVE_PAGE_LAYOUT = "SAVE_PAGE_LAYOUT",
|
||||
SAVE_ACTION = "SAVE_ACTION",
|
||||
EVALUATE_BINDING = "EVALUATE_BINDING",
|
||||
GENERATE_PROPERTY_PANE_PROPS = "GENERATE_PROPERTY_PANE_PROPS",
|
||||
GENERATE_VIEW_MODE_PROPS = "GENERATE_VIEW_MODE_PROPS",
|
||||
GENERATE_WIDGET_EDITOR_PROPS = "GENERATE_WIDGET_EDITOR_PROPS",
|
||||
ENTITY_EXPLORER_ENTITY = "ENTITY_EXPLORER_ENTITY",
|
||||
ENTITY_EXPLORER = "ENTITY_EXPLORER",
|
||||
CLOSE_API = "CLOSE_API",
|
||||
OPEN_API = "OPEN_API",
|
||||
CLOSE_SIDE_PANE = "CLOSE_SIDE_PANE",
|
||||
OPEN_ACTION = "OPEN_ACTION",
|
||||
EDITOR_MOUNT = "EDITOR_MOUNT",
|
||||
SIDE_BAR_MOUNT = "SIDE_BAR_MOUNT",
|
||||
CANVAS_MOUNT = "CANVAS_MOUNT",
|
||||
GENERATE_API_PROPS = "GENERATE_API_PROPS",
|
||||
EXECUTE_ACTION = "EXECUTE_ACTION",
|
||||
CHANGE_API_SAGA = "CHANGE_API_SAGA",
|
||||
SYNC_PARAMS_SAGA = "SYNC_PARAMS_SAGA",
|
||||
RUN_API_CLICK = "RUN_API_CLICK",
|
||||
RUN_QUERY_CLICK = "RUN_QUERY_CLICK",
|
||||
FETCH_ACTIONS_API = "FETCH_ACTIONS_API",
|
||||
FETCH_PAGE_LIST_API = "FETCH_PAGE_LIST_API",
|
||||
FETCH_PAGE_ACTIONS_API = "FETCH_PAGE_ACTIONS_API",
|
||||
FETCH_PAGE_API = "FETCH_PAGE_API",
|
||||
SAVE_PAGE_API = "SAVE_PAGE_API",
|
||||
UPDATE_ACTION_API = "UPDATE_ACTION_API",
|
||||
OPEN_PROPERTY_PANE = "OPEN_PROPERTY_PANE",
|
||||
REFACTOR_ACTION_NAME = "REFACTOR_ACTION_NAME",
|
||||
}
|
||||
|
||||
export enum PerformanceTagNames {
|
||||
|
|
@ -53,6 +51,7 @@ export interface PerfLog {
|
|||
|
||||
class PerformanceTracker {
|
||||
private static perfLogQueue: PerfLog[] = [];
|
||||
private static perfAsyncMap: Map<string, PerfLog> = new Map();
|
||||
|
||||
static startTracking = (
|
||||
eventName: PerformanceTransactionName,
|
||||
|
|
@ -84,6 +83,7 @@ class PerformanceTracker {
|
|||
);
|
||||
}
|
||||
const newTransaction = Sentry.startTransaction({ name: eventName });
|
||||
newTransaction.setData("startData", data);
|
||||
Sentry.getCurrentHub().configureScope(scope =>
|
||||
scope.setSpan(newTransaction),
|
||||
);
|
||||
|
|
@ -117,8 +117,8 @@ class PerformanceTracker {
|
|||
};
|
||||
|
||||
static stopTracking = (
|
||||
data?: any,
|
||||
eventName?: PerformanceTransactionName,
|
||||
data?: any,
|
||||
) => {
|
||||
if (eventName) {
|
||||
const index = _.findLastIndex(
|
||||
|
|
@ -128,9 +128,13 @@ class PerformanceTracker {
|
|||
},
|
||||
);
|
||||
if (index !== -1) {
|
||||
for (let i = PerformanceTracker.perfLogQueue.length - 1; i >= 0; i--) {
|
||||
const perfLog = PerformanceTracker.perfLogQueue[i];
|
||||
if (i >= index) {
|
||||
for (
|
||||
let i = PerformanceTracker.perfLogQueue.length - 1;
|
||||
i >= index;
|
||||
i--
|
||||
) {
|
||||
const perfLog = PerformanceTracker.perfLogQueue.pop();
|
||||
if (perfLog) {
|
||||
const currentSpan = perfLog.sentrySpan;
|
||||
currentSpan.finish();
|
||||
if (!perfLog?.skipLog) {
|
||||
|
|
@ -143,9 +147,6 @@ class PerformanceTracker {
|
|||
}
|
||||
}
|
||||
}
|
||||
PerformanceTracker.perfLogQueue = PerformanceTracker.perfLogQueue.splice(
|
||||
index,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const perfLog = PerformanceTracker.perfLogQueue.pop();
|
||||
|
|
@ -165,6 +166,69 @@ class PerformanceTracker {
|
|||
}
|
||||
};
|
||||
|
||||
static startAsyncTracking = (
|
||||
eventName: PerformanceTransactionName,
|
||||
data?: any,
|
||||
uniqueId?: string,
|
||||
parentEventId?: string,
|
||||
skipLog = false,
|
||||
) => {
|
||||
if (!skipLog) {
|
||||
log.debug(
|
||||
"Async " +
|
||||
PerformanceTracker.generateSpaces(0) +
|
||||
eventName +
|
||||
" Track Transaction ",
|
||||
);
|
||||
}
|
||||
if (!parentEventId) {
|
||||
const newTransaction = Sentry.startTransaction({ name: eventName });
|
||||
newTransaction.setData("startData", data);
|
||||
PerformanceTracker.perfAsyncMap.set(uniqueId ? uniqueId : eventName, {
|
||||
sentrySpan: newTransaction,
|
||||
eventName: eventName,
|
||||
skipLog: skipLog,
|
||||
});
|
||||
} else {
|
||||
const perfLog = PerformanceTracker.perfAsyncMap.get(parentEventId);
|
||||
const childSpan = perfLog?.sentrySpan.startChild({
|
||||
op: eventName,
|
||||
data: data,
|
||||
});
|
||||
if (childSpan) {
|
||||
PerformanceTracker.perfAsyncMap.set(uniqueId ? uniqueId : eventName, {
|
||||
sentrySpan: childSpan,
|
||||
eventName: eventName,
|
||||
skipLog: skipLog,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static stopAsyncTracking(
|
||||
eventName: PerformanceTransactionName,
|
||||
data?: any,
|
||||
uniqueId?: string,
|
||||
) {
|
||||
const perfLog = PerformanceTracker.perfAsyncMap.get(
|
||||
uniqueId ? uniqueId : eventName,
|
||||
);
|
||||
if (perfLog) {
|
||||
const currentSpan = perfLog.sentrySpan;
|
||||
currentSpan.setData("endData", data);
|
||||
currentSpan.finish();
|
||||
if (!perfLog?.skipLog) {
|
||||
PerformanceTracker.printDuration(
|
||||
perfLog.eventName,
|
||||
0,
|
||||
currentSpan.startTimestamp,
|
||||
currentSpan.endTimestamp,
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static generateSpaces(num: number) {
|
||||
let str = "";
|
||||
for (let i = 0; i < num; i++) {
|
||||
|
|
@ -178,10 +242,18 @@ class PerformanceTracker {
|
|||
level: number,
|
||||
startTime: number,
|
||||
endTime?: number,
|
||||
isAsync?: boolean,
|
||||
) {
|
||||
const duration = ((endTime || 0) - startTime) * 1000;
|
||||
const spaces = PerformanceTracker.generateSpaces(level);
|
||||
log.debug(spaces + eventName + " Finish Tracking in " + duration + "ms");
|
||||
log.debug(
|
||||
(isAsync ? "Async " : "") +
|
||||
spaces +
|
||||
eventName +
|
||||
" Finish Tracking in " +
|
||||
duration +
|
||||
"ms",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user