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:
Nikhil Nandagopal 2020-09-28 10:42:23 +05:30 committed by GitHub
parent dc1e2e124f
commit 3fdd0a246a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 353 additions and 67 deletions

View File

@ -192,6 +192,7 @@ export const executeApiActionRequest = (payload: { id: string }) => ({
export const executeApiActionSuccess = (payload: { export const executeApiActionSuccess = (payload: {
id: string; id: string;
response: ActionResponse; response: ActionResponse;
isPageLoad?: boolean;
}) => ({ }) => ({
type: ReduxActionTypes.EXECUTE_API_ACTION_SUCCESS, type: ReduxActionTypes.EXECUTE_API_ACTION_SUCCESS,
payload: payload, payload: payload,

View File

@ -9,6 +9,9 @@ import {
PageAction, PageAction,
} from "constants/ActionConstants"; } from "constants/ActionConstants";
import { BatchAction, batchAction } from "actions/batchActions"; import { BatchAction, batchAction } from "actions/batchActions";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
export const executeAction = ( export const executeAction = (
payload: ExecuteActionPayload, payload: ExecuteActionPayload,
@ -79,6 +82,9 @@ export const closeAllModals = () => {
}; };
export const forceOpenPropertyPane = (id: string) => { export const forceOpenPropertyPane = (id: string) => {
PerformanceTracker.startTracking(
PerformanceTransactionName.OPEN_PROPERTY_PANE,
);
return { return {
type: ReduxActionTypes.SHOW_PROPERTY_PANE, type: ReduxActionTypes.SHOW_PROPERTY_PANE,
payload: { payload: {

View File

@ -11,6 +11,9 @@ import {
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { WidgetType } from "constants/WidgetConstants"; import { WidgetType } from "constants/WidgetConstants";
import HelpControl from "./HelpControl"; import HelpControl from "./HelpControl";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
const PositionStyle = styled.div` const PositionStyle = styled.div`
position: absolute; position: absolute;
@ -68,6 +71,9 @@ export const WidgetNameComponent = (props: WidgetNameComponentProps) => {
props.widgetId === propertyPaneState.widgetId) || props.widgetId === propertyPaneState.widgetId) ||
props.widgetId !== propertyPaneState.widgetId props.widgetId !== propertyPaneState.widgetId
) { ) {
PerformanceTracker.startTracking(
PerformanceTransactionName.OPEN_PROPERTY_PANE,
);
AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN_CLICK", { AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN_CLICK", {
widgetType: props.type, widgetType: props.type,
widgetId: props.widgetId, widgetId: props.widgetId,

View File

@ -178,7 +178,7 @@ export const getAppsmithConfigs = (): AppsmithUIConfigs => {
routingInstrumentation: Sentry.reactRouterV5Instrumentation(history), routingInstrumentation: Sentry.reactRouterV5Instrumentation(history),
}), }),
], ],
tracesSampleRate: 1.0, tracesSampleRate: 0.5,
}, },
smartLook: { smartLook: {
enabled: smartLook.enabled, enabled: smartLook.enabled,

View File

@ -65,6 +65,7 @@ export interface PageAction {
export interface ExecuteErrorPayload { export interface ExecuteErrorPayload {
actionId: string; actionId: string;
error: any; error: any;
isPageLoad?: boolean;
} }
// Group 1 = datasource (https://www.domain.com) // Group 1 = datasource (https://www.domain.com)

View File

@ -17,9 +17,6 @@ import {
getCurrentPageName, getCurrentPageName,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import ConfirmRunModal from "pages/Editor/ConfirmRunModal"; import ConfirmRunModal from "pages/Editor/ConfirmRunModal";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
const Section = styled.section` const Section = styled.section`
background: ${props => props.theme.colors.bodyBG}; background: ${props => props.theme.colors.bodyBG};
@ -112,15 +109,11 @@ class AppViewerPageContainer extends Component<AppViewerPageContainerProps> {
} }
const mapStateToProps = (state: AppState) => { const mapStateToProps = (state: AppState) => {
PerformanceTracker.startTracking(
PerformanceTransactionName.GENERATE_VIEW_MODE_PROPS,
);
const props = { const props = {
isFetchingPage: getIsFetchingPage(state), isFetchingPage: getIsFetchingPage(state),
widgets: getCanvasWidgetDsl(state), widgets: getCanvasWidgetDsl(state),
currentPageName: getCurrentPageName(state), currentPageName: getCurrentPageName(state),
}; };
PerformanceTracker.stopTracking();
return props; return props;
}; };

View File

@ -40,8 +40,8 @@ const LoadingContainer = styled(CenteredWrapper)`
interface ReduxStateProps { interface ReduxStateProps {
actions: ActionDataState; actions: ActionDataState;
isRunning: Record<string, boolean>; isRunning: boolean;
isDeleting: Record<string, boolean>; isDeleting: boolean;
isCreating: boolean; isCreating: boolean;
apiName: string; apiName: string;
currentApplication: UserApplication; currentApplication: UserApplication;
@ -71,6 +71,9 @@ type Props = ReduxActionProps &
class ApiEditor extends React.Component<Props> { class ApiEditor extends React.Component<Props> {
componentDidMount() { componentDidMount() {
PerformanceTracker.stopTracking(PerformanceTransactionName.OPEN_ACTION, {
actionType: "API",
});
this.props.changeAPIPage(this.props.match.params.apiId); this.props.changeAPIPage(this.props.match.params.apiId);
} }
handleDeleteClick = () => { handleDeleteClick = () => {
@ -87,6 +90,9 @@ class ApiEditor extends React.Component<Props> {
}; };
componentDidUpdate(prevProps: 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) { if (prevProps.match.params.apiId !== this.props.match.params.apiId) {
this.props.changeAPIPage(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.pages,
this.props.match.params.pageId, this.props.match.params.pageId,
); );
PerformanceTracker.startTracking(PerformanceTransactionName.RUN_API_CLICK, {
apiId: this.props.match.params.apiId,
});
AnalyticsUtil.logEvent("RUN_API_CLICK", { AnalyticsUtil.logEvent("RUN_API_CLICK", {
apiName: this.props.apiName, apiName: this.props.apiName,
apiID: this.props.match.params.apiId, apiID: this.props.match.params.apiId,
@ -174,8 +183,8 @@ class ApiEditor extends React.Component<Props> {
<ApiEditorForm <ApiEditorForm
pluginId={pluginId} pluginId={pluginId}
paginationType={paginationType} paginationType={paginationType}
isRunning={isRunning[apiId]} isRunning={isRunning}
isDeleting={isDeleting[apiId]} isDeleting={isDeleting}
onDeleteClick={this.handleDeleteClick} onDeleteClick={this.handleDeleteClick}
onRunClick={this.handleRunClick} onRunClick={this.handleRunClick}
appName={ appName={
@ -192,8 +201,8 @@ class ApiEditor extends React.Component<Props> {
apiName={this.props.apiName} apiName={this.props.apiName}
apiId={this.props.match.params.apiId} apiId={this.props.match.params.apiId}
paginationType={paginationType} paginationType={paginationType}
isRunning={isRunning[apiId]} isRunning={isRunning}
isDeleting={isDeleting[apiId]} isDeleting={isDeleting}
onDeleteClick={this.handleDeleteClick} onDeleteClick={this.handleDeleteClick}
onRunClick={this.handleRunClick} onRunClick={this.handleRunClick}
appName={ appName={
@ -217,9 +226,6 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
const apiAction = getActionById(state, props); const apiAction = getActionById(state, props);
const apiName = getApiName(state, props.match.params.apiId); const apiName = getApiName(state, props.match.params.apiId);
const { isDeleting, isRunning, isCreating } = state.ui.apiPane; const { isDeleting, isRunning, isCreating } = state.ui.apiPane;
PerformanceTracker.startTracking(
PerformanceTransactionName.GENERATE_API_PROPS,
);
const apiEditorState = { const apiEditorState = {
actions: state.entities.actions, actions: state.entities.actions,
currentApplication: getCurrentApplication(state), currentApplication: getCurrentApplication(state),
@ -230,12 +236,11 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
pluginId: _.get(apiAction, "pluginId"), pluginId: _.get(apiAction, "pluginId"),
paginationType: _.get(apiAction, "actionConfiguration.paginationType"), paginationType: _.get(apiAction, "actionConfiguration.paginationType"),
apiAction, apiAction,
isRunning, isRunning: isRunning[props.match.params.apiId],
isDeleting, isDeleting: isDeleting[props.match.params.apiId],
isCreating, isCreating: isCreating,
isEditorInitialized: getIsEditorInitialized(state), isEditorInitialized: getIsEditorInitialized(state),
}; };
PerformanceTracker.stopTracking();
return apiEditorState; return apiEditorState;
}; };

View File

@ -7,6 +7,9 @@ import EntityProperties from "../Entity/EntityProperties";
import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory"; import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
import { ExplorerURLParams } from "../helpers"; import { ExplorerURLParams } from "../helpers";
import { useParams } from "react-router"; import { useParams } from "react-router";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
const getUpdateActionNameReduxAction = (id: string, name: string) => { const getUpdateActionNameReduxAction = (id: string, name: string) => {
return saveActionName({ id, name }); return saveActionName({ id, name });
@ -25,6 +28,9 @@ type ExplorerActionEntityProps = {
export const ExplorerActionEntity = memo((props: ExplorerActionEntityProps) => { export const ExplorerActionEntity = memo((props: ExplorerActionEntityProps) => {
const { pageId } = useParams<ExplorerURLParams>(); const { pageId } = useParams<ExplorerURLParams>();
const switchToAction = useCallback(() => { const switchToAction = useCallback(() => {
PerformanceTracker.startTracking(PerformanceTransactionName.OPEN_ACTION, {
url: props.url,
});
props.url && history.push(props.url); props.url && history.push(props.url);
}, [props.url]); }, [props.url]);

View File

@ -26,7 +26,9 @@ export const EntityProperties = (props: {
PerformanceTransactionName.ENTITY_EXPLORER_ENTITY, PerformanceTransactionName.ENTITY_EXPLORER_ENTITY,
); );
useEffect(() => { useEffect(() => {
PerformanceTracker.stopTracking(); PerformanceTracker.stopTracking(
PerformanceTransactionName.ENTITY_EXPLORER_ENTITY,
);
}); });
let entity: any; let entity: any;
const dataTree: DataTree = useSelector(evaluateDataTreeWithoutFunctions); const dataTree: DataTree = useSelector(evaluateDataTreeWithoutFunctions);

View File

@ -175,11 +175,20 @@ class PropertyPane extends Component<
} }
}; };
componentDidMount() {
PerformanceTracker.stopTracking(
PerformanceTransactionName.OPEN_PROPERTY_PANE,
);
}
componentDidUpdate(prevProps: PropertyPaneProps & PropertyPaneFunctions) { componentDidUpdate(prevProps: PropertyPaneProps & PropertyPaneFunctions) {
if ( if (
this.props.widgetId !== prevProps.widgetId && this.props.widgetId !== prevProps.widgetId &&
this.props.widgetId !== undefined this.props.widgetId !== undefined
) { ) {
PerformanceTracker.stopTracking(
PerformanceTransactionName.OPEN_PROPERTY_PANE,
);
if (prevProps.widgetId && prevProps.widgetProperties) { if (prevProps.widgetId && prevProps.widgetProperties) {
AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE", { AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE", {
widgetType: prevProps.widgetProperties.type, widgetType: prevProps.widgetProperties.type,
@ -227,16 +236,12 @@ class PropertyPane extends Component<
} }
const mapStateToProps = (state: AppState): PropertyPaneProps => { const mapStateToProps = (state: AppState): PropertyPaneProps => {
PerformanceTracker.startTracking(
PerformanceTransactionName.GENERATE_PROPERTY_PANE_PROPS,
);
const props = { const props = {
propertySections: getPropertyConfig(state), propertySections: getPropertyConfig(state),
widgetId: getCurrentWidgetId(state), widgetId: getCurrentWidgetId(state),
widgetProperties: getWidgetPropsForPropertyPane(state), widgetProperties: getWidgetPropsForPropertyPane(state),
isVisible: getIsPropertyPaneVisible(state), isVisible: getIsPropertyPaneVisible(state),
}; };
PerformanceTracker.stopTracking();
return props; return props;
}; };

View File

@ -12,7 +12,6 @@ import { getIsEditorInitialized } from "selectors/editorSelectors";
import { QUERY_EDITOR_FORM_NAME } from "constants/forms"; import { QUERY_EDITOR_FORM_NAME } from "constants/forms";
import { Plugin } from "api/PluginApi"; import { Plugin } from "api/PluginApi";
import { Datasource } from "api/DatasourcesApi"; import { Datasource } from "api/DatasourcesApi";
import { QueryPaneReduxState } from "reducers/uiReducers/queryPaneReducer";
import { import {
getPluginIdsOfPackageNames, getPluginIdsOfPackageNames,
getPlugins, getPlugins,
@ -26,6 +25,10 @@ import { QueryAction } from "entities/Action";
import Spinner from "components/editorComponents/Spinner"; import Spinner from "components/editorComponents/Spinner";
import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper"; import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper";
import { changeQuery } from "actions/queryPaneActions"; import { changeQuery } from "actions/queryPaneActions";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
import AnalyticsUtil from "utils/AnalyticsUtil";
const EmptyStateContainer = styled.div` const EmptyStateContainer = styled.div`
display: flex; display: flex;
@ -46,7 +49,8 @@ type ReduxDispatchProps = {
type ReduxStateProps = { type ReduxStateProps = {
plugins: Plugin[]; plugins: Plugin[];
dataSources: Datasource[]; dataSources: Datasource[];
queryPane: QueryPaneReduxState; isRunning: boolean;
isDeleting: boolean;
formData: QueryAction; formData: QueryAction;
runErrorMessage: Record<string, string>; runErrorMessage: Record<string, string>;
pluginIds: Array<string> | undefined; pluginIds: Array<string> | undefined;
@ -65,6 +69,9 @@ type Props = StateAndRouteProps & ReduxDispatchProps & ReduxStateProps;
class QueryEditor extends React.Component<Props> { class QueryEditor extends React.Component<Props> {
componentDidMount() { componentDidMount() {
this.props.changeQueryPage(this.props.match.params.queryId); this.props.changeQueryPage(this.props.match.params.queryId);
PerformanceTracker.stopTracking(PerformanceTransactionName.OPEN_ACTION, {
actionType: "QUERY",
});
} }
handleDeleteClick = () => { handleDeleteClick = () => {
const { queryId } = this.props.match.params; const { queryId } = this.props.match.params;
@ -74,10 +81,22 @@ class QueryEditor extends React.Component<Props> {
handleRunClick = () => { handleRunClick = () => {
const { match } = this.props; 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); this.props.runAction(match.params.queryId);
}; };
componentDidUpdate(prevProps: Props) { 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) { if (prevProps.match.params.queryId !== this.props.match.params.queryId) {
this.props.changeQueryPage(this.props.match.params.queryId); this.props.changeQueryPage(this.props.match.params.queryId);
} }
@ -86,7 +105,8 @@ class QueryEditor extends React.Component<Props> {
render() { render() {
const { const {
dataSources, dataSources,
queryPane, isRunning,
isDeleting,
match: { match: {
params: { queryId }, params: { queryId },
}, },
@ -114,7 +134,6 @@ class QueryEditor extends React.Component<Props> {
</LoadingContainer> </LoadingContainer>
); );
} }
const { isRunning, isDeleting } = queryPane;
const DATASOURCES_OPTIONS = dataSources.map(dataSource => ({ const DATASOURCES_OPTIONS = dataSources.map(dataSource => ({
label: dataSource.name, label: dataSource.name,
@ -128,8 +147,8 @@ class QueryEditor extends React.Component<Props> {
location={this.props.location} location={this.props.location}
applicationId={applicationId} applicationId={applicationId}
pageId={pageId} pageId={pageId}
isRunning={isRunning[queryId]} isRunning={isRunning}
isDeleting={isDeleting[queryId]} isDeleting={isDeleting}
onDeleteClick={this.handleDeleteClick} onDeleteClick={this.handleDeleteClick}
onRunClick={this.handleRunClick} onRunClick={this.handleRunClick}
dataSources={dataSources} dataSources={dataSources}
@ -175,7 +194,8 @@ const mapStateToProps = (state: AppState, props: any): ReduxStateProps => {
pluginIds: getPluginIdsOfPackageNames(state, PLUGIN_PACKAGE_DBS), pluginIds: getPluginIdsOfPackageNames(state, PLUGIN_PACKAGE_DBS),
dataSources: getDBDatasources(state), dataSources: getDBDatasources(state),
responses: getActionResponses(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, formData,
editorConfig, editorConfig,
loadingFormConfigs, loadingFormConfigs,

View File

@ -61,7 +61,7 @@ const WidgetsEditor = () => {
useEffect(() => { useEffect(() => {
PerformanceTracker.stopTracking(PerformanceTransactionName.EDITOR_MOUNT); PerformanceTracker.stopTracking(PerformanceTransactionName.EDITOR_MOUNT);
PerformanceTracker.stopTracking(PerformanceTransactionName.CLOSE_API); PerformanceTracker.stopTracking(PerformanceTransactionName.CLOSE_SIDE_PANE);
}); });
// Switch page // Switch page

View File

@ -88,7 +88,10 @@ class EditorsRouter extends React.Component<
} }
handleClose = (e: React.MouseEvent) => { handleClose = (e: React.MouseEvent) => {
PerformanceTracker.startTracking(PerformanceTransactionName.CLOSE_API); PerformanceTracker.startTracking(
PerformanceTransactionName.CLOSE_SIDE_PANE,
{ path: this.props.location.pathname },
);
e.stopPropagation(); e.stopPropagation();
const { applicationId, pageId } = this.props.match.params; const { applicationId, pageId } = this.props.match.params;
this.setState({ this.setState({

View File

@ -66,9 +66,14 @@ const editorReducer = createReducer(initialState, {
[ReduxActionErrorTypes.INITIALIZE_EDITOR_ERROR]: ( [ReduxActionErrorTypes.INITIALIZE_EDITOR_ERROR]: (
state: EditorReduxState, state: EditorReduxState,
) => { ) => {
state.loadingStates.loading = false; return {
state.loadingStates.loadingError = true; ...state,
return { ...state }; loadingStates: {
...state.loadingStates,
loading: false,
loadingError: true,
},
};
}, },
[ReduxActionTypes.PUBLISH_APPLICATION_INIT]: (state: EditorReduxState) => { [ReduxActionTypes.PUBLISH_APPLICATION_INIT]: (state: EditorReduxState) => {
state.loadingStates.publishing = true; state.loadingStates.publishing = true;

View File

@ -77,6 +77,9 @@ import { updateAppStore } from "actions/pageActions";
import { getAppStoreName } from "constants/AppConstants"; import { getAppStoreName } from "constants/AppConstants";
import downloadjs from "downloadjs"; import downloadjs from "downloadjs";
import { getType, Types } from "utils/TypeHelpers"; import { getType, Types } from "utils/TypeHelpers";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
function* navigateActionSaga( function* navigateActionSaga(
action: { pageNameOrUrl: string; params: Record<string, string> }, action: { pageNameOrUrl: string; params: Record<string, string> },
@ -283,6 +286,13 @@ export function* executeActionSaga(
event: ExecuteActionPayloadEvent, event: ExecuteActionPayloadEvent,
) { ) {
const { actionId, onSuccess, onError, params } = apiAction; const { actionId, onSuccess, onError, params } = apiAction;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
{
actionId: actionId,
},
actionId,
);
try { try {
const api: RestAction = yield select(getAction, actionId); const api: RestAction = yield select(getAction, actionId);
@ -326,6 +336,11 @@ export function* executeActionSaga(
}), }),
); );
if (isErrorResponse(response)) { if (isErrorResponse(response)) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
{ failed: true },
actionId,
);
if (onError) { if (onError) {
yield put( yield put(
executeAction({ executeAction({
@ -348,6 +363,11 @@ export function* executeActionSaga(
type: "error", type: "error",
}); });
} else { } else {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
undefined,
actionId,
);
if (onSuccess) { if (onSuccess) {
yield put( yield put(
executeAction({ executeAction({
@ -579,6 +599,14 @@ function* confirmRunActionSaga() {
} }
function* executePageLoadAction(pageAction: PageAction) { 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 })); yield put(executeApiActionRequest({ id: pageAction.id }));
const params: Property[] = yield call( const params: Property[] = yield call(
getActionParams, getActionParams,
@ -592,20 +620,33 @@ function* executePageLoadAction(pageAction: PageAction) {
executeActionRequest, executeActionRequest,
pageAction.timeoutInMillisecond, pageAction.timeoutInMillisecond,
); );
if (isErrorResponse(response)) { if (isErrorResponse(response)) {
yield put( yield put(
executeActionError({ executeActionError({
actionId: pageAction.id, actionId: pageAction.id,
error: response.responseMeta.error, error: response.responseMeta.error,
isPageLoad: true,
}), }),
); );
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
{
failed: true,
},
pageAction.id,
);
} else { } else {
const payload = createActionExecutionResponse(response); const payload = createActionExecutionResponse(response);
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
undefined,
pageAction.id,
);
yield put( yield put(
executeApiActionSuccess({ executeApiActionSuccess({
id: pageAction.id, id: pageAction.id,
response: payload, response: payload,
isPageLoad: true,
}), }),
); );
} }
@ -613,10 +654,20 @@ function* executePageLoadAction(pageAction: PageAction) {
function* executePageLoadActionsSaga(action: ReduxAction<PageAction[][]>) { function* executePageLoadActionsSaga(action: ReduxAction<PageAction[][]>) {
const pageActions = action.payload; const pageActions = action.payload;
const actionCount = _.flatten(pageActions).length;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
{ numActions: actionCount },
);
for (const actionSet of pageActions) { for (const actionSet of pageActions) {
// Load all sets in parallel // 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() { export function* watchActionExecutionSagas() {

View File

@ -60,6 +60,9 @@ import {
QUERIES_EDITOR_ID_URL, QUERIES_EDITOR_ID_URL,
API_EDITOR_ID_URL, API_EDITOR_ID_URL,
} from "constants/routes"; } from "constants/routes";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
export function* createActionSaga(actionPayload: ReduxAction<RestAction>) { export function* createActionSaga(actionPayload: ReduxAction<RestAction>) {
try { try {
@ -94,8 +97,12 @@ export function* createActionSaga(actionPayload: ReduxAction<RestAction>) {
} }
export function* fetchActionsSaga(action: ReduxAction<FetchActionsPayload>) { export function* fetchActionsSaga(action: ReduxAction<FetchActionsPayload>) {
try {
const { applicationId } = action.payload; const { applicationId } = action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ mode: "EDITOR", appId: applicationId },
);
try {
const response: GenericApiResponse<RestAction[]> = yield ActionAPI.fetchActions( const response: GenericApiResponse<RestAction[]> = yield ActionAPI.fetchActions(
applicationId, applicationId,
); );
@ -105,20 +112,31 @@ export function* fetchActionsSaga(action: ReduxAction<FetchActionsPayload>) {
type: ReduxActionTypes.FETCH_ACTIONS_SUCCESS, type: ReduxActionTypes.FETCH_ACTIONS_SUCCESS,
payload: response.data, payload: response.data,
}); });
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
);
} }
} catch (error) { } catch (error) {
yield put({ yield put({
type: ReduxActionErrorTypes.FETCH_ACTIONS_ERROR, type: ReduxActionErrorTypes.FETCH_ACTIONS_ERROR,
payload: { error }, payload: { error },
}); });
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ failed: true },
);
} }
} }
export function* fetchActionsForViewModeSaga( export function* fetchActionsForViewModeSaga(
action: ReduxAction<FetchActionsPayload>, action: ReduxAction<FetchActionsPayload>,
) { ) {
try {
const { applicationId } = action.payload; const { applicationId } = action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ mode: "VIEWER", appId: applicationId },
);
try {
const response: GenericApiResponse<RestAction[]> = yield ActionAPI.fetchActionsForViewMode( const response: GenericApiResponse<RestAction[]> = yield ActionAPI.fetchActionsForViewMode(
applicationId, applicationId,
); );
@ -128,20 +146,31 @@ export function* fetchActionsForViewModeSaga(
type: ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS, type: ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS,
payload: response.data, payload: response.data,
}); });
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
);
} }
} catch (error) { } catch (error) {
yield put({ yield put({
type: ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR, type: ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR,
payload: { error }, payload: { error },
}); });
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ failed: true },
);
} }
} }
export function* fetchActionsForPageSaga( export function* fetchActionsForPageSaga(
action: ReduxAction<{ pageId: string }>, action: ReduxAction<{ pageId: string }>,
) { ) {
try {
const { pageId } = action.payload; const { pageId } = action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
{ pageId: pageId },
);
try {
const response: GenericApiResponse<RestAction[]> = yield call( const response: GenericApiResponse<RestAction[]> = yield call(
ActionAPI.fetchActionsByPageId, ActionAPI.fetchActionsByPageId,
pageId, pageId,
@ -149,8 +178,15 @@ export function* fetchActionsForPageSaga(
const isValidResponse = yield validateResponse(response); const isValidResponse = yield validateResponse(response);
if (isValidResponse) { if (isValidResponse) {
yield put(fetchActionsForPageSuccess(response.data)); yield put(fetchActionsForPageSuccess(response.data));
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
);
} }
} catch (error) { } catch (error) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
{ failed: true },
);
yield put({ yield put({
type: ReduxActionErrorTypes.FETCH_ACTIONS_FOR_PAGE_ERROR, type: ReduxActionErrorTypes.FETCH_ACTIONS_FOR_PAGE_ERROR,
payload: { error }, payload: { error },
@ -160,6 +196,10 @@ export function* fetchActionsForPageSaga(
export function* updateActionSaga(actionPayload: ReduxAction<{ id: string }>) { export function* updateActionSaga(actionPayload: ReduxAction<{ id: string }>) {
try { try {
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.UPDATE_ACTION_API,
{ actionid: actionPayload.payload.id },
);
let action: Action = yield select(getAction, actionPayload.payload.id); let action: Action = yield select(getAction, actionPayload.payload.id);
const isApi = action.pluginType === "API"; const isApi = action.pluginType === "API";
const isDB = action.pluginType === "DB"; const isDB = action.pluginType === "DB";
@ -193,10 +233,16 @@ export function* updateActionSaga(actionPayload: ReduxAction<{ id: string }>) {
pageName: pageName, pageName: pageName,
}); });
} }
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.UPDATE_ACTION_API,
);
yield put(updateActionSuccess({ data: response.data })); yield put(updateActionSuccess({ data: response.data }));
} }
} catch (error) { } catch (error) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.UPDATE_ACTION_API,
{ failed: true },
);
yield put({ yield put({
type: ReduxActionErrorTypes.UPDATE_ACTION_ERROR, type: ReduxActionErrorTypes.UPDATE_ACTION_ERROR,
payload: { error, id: actionPayload.payload.id }, payload: { error, id: actionPayload.payload.id },
@ -350,6 +396,10 @@ export function* refactorActionName(
newName: string, newName: string,
) { ) {
// fetch page of the action // fetch page of the action
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.REFACTOR_ACTION_NAME,
{ actionId: id },
);
const pageResponse = yield call(PageApi.fetchPage, { const pageResponse = yield call(PageApi.fetchPage, {
id: pageId, id: pageId,
}); });
@ -369,6 +419,11 @@ export function* refactorActionName(
const isRefactorSuccessful = yield validateResponse(refactorResponse); const isRefactorSuccessful = yield validateResponse(refactorResponse);
const currentPageId = yield select(getCurrentPageId); const currentPageId = yield select(getCurrentPageId);
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.REFACTOR_ACTION_NAME,
{ isSuccess: isRefactorSuccessful },
);
if (isRefactorSuccessful) { if (isRefactorSuccessful) {
yield put({ yield put({
type: ReduxActionTypes.SAVE_ACTION_NAME_SUCCESS, type: ReduxActionTypes.SAVE_ACTION_NAME_SUCCESS,

View File

@ -72,6 +72,9 @@ import {
import { clearCaches } from "utils/DynamicBindingUtils"; import { clearCaches } from "utils/DynamicBindingUtils";
import { UrlDataState } from "reducers/entityReducers/appReducer"; import { UrlDataState } from "reducers/entityReducers/appReducer";
import { getQueryParams } from "utils/AppsmithUtils"; import { getQueryParams } from "utils/AppsmithUtils";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
const getWidgetName = (state: AppState, widgetId: string) => const getWidgetName = (state: AppState, widgetId: string) =>
state.entities.canvasWidgets[widgetId]; state.entities.canvasWidgets[widgetId];
@ -79,6 +82,9 @@ const getWidgetName = (state: AppState, widgetId: string) =>
export function* fetchPageListSaga( export function* fetchPageListSaga(
fetchPageListAction: ReduxAction<FetchPageListPayload>, fetchPageListAction: ReduxAction<FetchPageListPayload>,
) { ) {
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_LIST_API,
);
try { try {
const { applicationId } = fetchPageListAction.payload; const { applicationId } = fetchPageListAction.payload;
const response: FetchPageListResponse = yield call( const response: FetchPageListResponse = yield call(
@ -106,8 +112,15 @@ export function* fetchPageListSaga(
applicationId, applicationId,
}, },
}); });
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_LIST_API,
);
} }
} catch (error) { } catch (error) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_LIST_API,
{ failed: true },
);
yield put({ yield put({
type: ReduxActionErrorTypes.FETCH_PAGE_LIST_ERROR, type: ReduxActionErrorTypes.FETCH_PAGE_LIST_ERROR,
payload: { payload: {
@ -139,6 +152,10 @@ export function* fetchPageSaga(
) { ) {
try { try {
const { id } = pageRequestAction.payload; const { id } = pageRequestAction.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
{ pageId: id },
);
const fetchPageResponse: FetchPageResponse = yield call(PageApi.fetchPage, { const fetchPageResponse: FetchPageResponse = yield call(PageApi.fetchPage, {
id, id,
}); });
@ -167,9 +184,18 @@ export function* fetchPageSaga(
dsl: extractCurrentDSL(fetchPageResponse), dsl: extractCurrentDSL(fetchPageResponse),
}, },
}); });
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
);
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
{
failed: true,
},
);
yield put({ yield put({
type: ReduxActionErrorTypes.FETCH_PAGE_ERROR, type: ReduxActionErrorTypes.FETCH_PAGE_ERROR,
payload: { payload: {
@ -184,6 +210,10 @@ export function* fetchPublishedPageSaga(
) { ) {
try { try {
const { pageId, bustCache } = pageRequestAction.payload; const { pageId, bustCache } = pageRequestAction.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
{ pageId: pageId, published: true },
);
const request: FetchPublishedPageRequest = { const request: FetchPublishedPageRequest = {
pageId, pageId,
bustCache, bustCache,
@ -213,9 +243,18 @@ export function* fetchPublishedPageSaga(
}), }),
); );
// Execute page load actions // Execute page load actions
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
);
yield put(executePageLoadActions(canvasWidgetsPayload.pageActions)); yield put(executePageLoadActions(canvasWidgetsPayload.pageActions));
} }
} catch (error) { } catch (error) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_API,
{
failed: true,
},
);
yield put({ yield put({
type: ReduxActionErrorTypes.FETCH_PUBLISHED_PAGE_ERROR, type: ReduxActionErrorTypes.FETCH_PUBLISHED_PAGE_ERROR,
payload: { payload: {
@ -242,6 +281,12 @@ function* savePageSaga() {
const widgets = yield select(getWidgets); const widgets = yield select(getWidgets);
const editorConfigs = yield select(getEditorConfigs) as any; const editorConfigs = yield select(getEditorConfigs) as any;
const savePageRequest = getLayoutSavePayload(widgets, editorConfigs); const savePageRequest = getLayoutSavePayload(widgets, editorConfigs);
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.SAVE_PAGE_API,
{
pageId: savePageRequest.pageId,
},
);
try { try {
// Store the updated DSL in the pageDSLs reducer // Store the updated DSL in the pageDSLs reducer
yield put({ yield put({
@ -266,8 +311,17 @@ function* savePageSaga() {
} }
} }
yield put(savePageSuccess(savePageResponse)); yield put(savePageSuccess(savePageResponse));
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.SAVE_PAGE_API,
);
} }
} catch (error) { } catch (error) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.SAVE_PAGE_API,
{
failed: true,
},
);
yield put({ yield put({
type: ReduxActionErrorTypes.SAVE_PAGE_ERROR, type: ReduxActionErrorTypes.SAVE_PAGE_ERROR,
payload: { payload: {

View File

@ -45,6 +45,7 @@ export type EventName =
| "DUPLICATE_API" | "DUPLICATE_API"
| "DUPLICATE_API_CLICK" | "DUPLICATE_API_CLICK"
| "RUN_QUERY" | "RUN_QUERY"
| "RUN_QUERY_CLICK"
| "DELETE_QUERY" | "DELETE_QUERY"
| "SAVE_QUERY" | "SAVE_QUERY"
| "MOVE_API" | "MOVE_API"

View File

@ -5,13 +5,6 @@ import * as log from "loglevel";
export enum PerformanceTransactionName { export enum PerformanceTransactionName {
DEPLOY_APPLICATION = "DEPLOY_APPLICATION", 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", DATA_TREE_EVALUATION = "DATA_TREE_EVALUATION",
CONSTRUCT_UNEVAL_TREE = "CONSTRUCT_UNEVAL_TREE", CONSTRUCT_UNEVAL_TREE = "CONSTRUCT_UNEVAL_TREE",
CONSTRUCT_CANVAS_DSL = "CONSTRUCT_CANVAS_DSL", CONSTRUCT_CANVAS_DSL = "CONSTRUCT_CANVAS_DSL",
@ -20,22 +13,27 @@ export enum PerformanceTransactionName {
SET_WIDGET_LOADING = "SET_WIDGET_LOADING", SET_WIDGET_LOADING = "SET_WIDGET_LOADING",
VALIDATE_DATA_TREE = "VALIDATE_DATA_TREE", VALIDATE_DATA_TREE = "VALIDATE_DATA_TREE",
EXECUTE_PAGE_LOAD_ACTIONS = "EXECUTE_PAGE_LOAD_ACTIONS", EXECUTE_PAGE_LOAD_ACTIONS = "EXECUTE_PAGE_LOAD_ACTIONS",
SAVE_PAGE_LAYOUT = "SAVE_PAGE_LAYOUT",
SAVE_ACTION = "SAVE_ACTION",
EVALUATE_BINDING = "EVALUATE_BINDING", 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 = "ENTITY_EXPLORER_ENTITY",
ENTITY_EXPLORER = "ENTITY_EXPLORER", ENTITY_EXPLORER = "ENTITY_EXPLORER",
CLOSE_API = "CLOSE_API", CLOSE_SIDE_PANE = "CLOSE_SIDE_PANE",
OPEN_API = "OPEN_API", OPEN_ACTION = "OPEN_ACTION",
EDITOR_MOUNT = "EDITOR_MOUNT", EDITOR_MOUNT = "EDITOR_MOUNT",
SIDE_BAR_MOUNT = "SIDE_BAR_MOUNT", SIDE_BAR_MOUNT = "SIDE_BAR_MOUNT",
CANVAS_MOUNT = "CANVAS_MOUNT", CANVAS_MOUNT = "CANVAS_MOUNT",
GENERATE_API_PROPS = "GENERATE_API_PROPS", EXECUTE_ACTION = "EXECUTE_ACTION",
CHANGE_API_SAGA = "CHANGE_API_SAGA", CHANGE_API_SAGA = "CHANGE_API_SAGA",
SYNC_PARAMS_SAGA = "SYNC_PARAMS_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 { export enum PerformanceTagNames {
@ -53,6 +51,7 @@ export interface PerfLog {
class PerformanceTracker { class PerformanceTracker {
private static perfLogQueue: PerfLog[] = []; private static perfLogQueue: PerfLog[] = [];
private static perfAsyncMap: Map<string, PerfLog> = new Map();
static startTracking = ( static startTracking = (
eventName: PerformanceTransactionName, eventName: PerformanceTransactionName,
@ -84,6 +83,7 @@ class PerformanceTracker {
); );
} }
const newTransaction = Sentry.startTransaction({ name: eventName }); const newTransaction = Sentry.startTransaction({ name: eventName });
newTransaction.setData("startData", data);
Sentry.getCurrentHub().configureScope(scope => Sentry.getCurrentHub().configureScope(scope =>
scope.setSpan(newTransaction), scope.setSpan(newTransaction),
); );
@ -117,8 +117,8 @@ class PerformanceTracker {
}; };
static stopTracking = ( static stopTracking = (
data?: any,
eventName?: PerformanceTransactionName, eventName?: PerformanceTransactionName,
data?: any,
) => { ) => {
if (eventName) { if (eventName) {
const index = _.findLastIndex( const index = _.findLastIndex(
@ -128,9 +128,13 @@ class PerformanceTracker {
}, },
); );
if (index !== -1) { if (index !== -1) {
for (let i = PerformanceTracker.perfLogQueue.length - 1; i >= 0; i--) { for (
const perfLog = PerformanceTracker.perfLogQueue[i]; let i = PerformanceTracker.perfLogQueue.length - 1;
if (i >= index) { i >= index;
i--
) {
const perfLog = PerformanceTracker.perfLogQueue.pop();
if (perfLog) {
const currentSpan = perfLog.sentrySpan; const currentSpan = perfLog.sentrySpan;
currentSpan.finish(); currentSpan.finish();
if (!perfLog?.skipLog) { if (!perfLog?.skipLog) {
@ -143,9 +147,6 @@ class PerformanceTracker {
} }
} }
} }
PerformanceTracker.perfLogQueue = PerformanceTracker.perfLogQueue.splice(
index,
);
} }
} else { } else {
const perfLog = PerformanceTracker.perfLogQueue.pop(); 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) { static generateSpaces(num: number) {
let str = ""; let str = "";
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
@ -178,10 +242,18 @@ class PerformanceTracker {
level: number, level: number,
startTime: number, startTime: number,
endTime?: number, endTime?: number,
isAsync?: boolean,
) { ) {
const duration = ((endTime || 0) - startTime) * 1000; const duration = ((endTime || 0) - startTime) * 1000;
const spaces = PerformanceTracker.generateSpaces(level); 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",
);
} }
} }