diff --git a/app/client/build.sh b/app/client/build.sh index 146c6d355f..bc8184cfd8 100755 --- a/app/client/build.sh +++ b/app/client/build.sh @@ -18,6 +18,12 @@ export REACT_APP_SENTRY_RELEASE=$GIT_SHA export REACT_APP_CLIENT_LOG_LEVEL=ERROR # Disable CRA built-in ESLint checks since we have our own config and a separate step for this export DISABLE_ESLINT_PLUGIN=true -craco --max-old-space-size=7168 build --config craco.build.config.js +if [ "$APPSMITH_CLOUD_HOSTING" == "true" ]; then + echo "Building profiled build" + craco --max-old-space-size=7168 build --profile --config craco.build.config.js --verbose +else + craco --max-old-space-size=7168 build --config craco.build.config.js +fi + echo "build finished" diff --git a/app/client/src/UITelemetry/auto-otel-web.ts b/app/client/src/UITelemetry/auto-otel-web.ts index 6365b99279..389e5e04fd 100644 --- a/app/client/src/UITelemetry/auto-otel-web.ts +++ b/app/client/src/UITelemetry/auto-otel-web.ts @@ -39,6 +39,7 @@ const tracerProvider = new WebTracerProvider({ const nrTracesExporter = new OTLPTraceExporter({ url: `${otlpEndpoint}/v1/traces`, + compression: CompressionAlgorithm.GZIP, headers: { "api-key": otlpLicenseKey, }, diff --git a/app/client/src/UITelemetry/generateTraces.ts b/app/client/src/UITelemetry/generateTraces.ts index c051fa0840..71b417a732 100644 --- a/app/client/src/UITelemetry/generateTraces.ts +++ b/app/client/src/UITelemetry/generateTraces.ts @@ -91,3 +91,15 @@ export function wrapFnWithParentTraceContext(parentSpan: Span, fn: () => any) { const parentContext = trace.setSpan(context.active(), parentSpan); return context.with(parentContext, fn); } + +export function startAndEndSpan( + spanName: string, + startTime: number, + difference: number, + spanAttributes: SpanAttributes = {}, +) { + const endTime = startTime + Math.floor(difference); + + const span = startRootSpan(spanName, spanAttributes, startTime); + span.end(endTime); +} diff --git a/app/client/src/widgets/BaseWidgetHOC/WidgetProfiler.tsx b/app/client/src/widgets/BaseWidgetHOC/WidgetProfiler.tsx new file mode 100644 index 0000000000..28deff6ce3 --- /dev/null +++ b/app/client/src/widgets/BaseWidgetHOC/WidgetProfiler.tsx @@ -0,0 +1,27 @@ +import React, { Profiler, useCallback } from "react"; +import { startAndEndSpan } from "UITelemetry/generateTraces"; +export const WidgetProfiler = ({ + children, + type, + widgetId, +}: { + children: React.ReactNode; + type: string; + widgetId: string; +}) => { + const onRender = useCallback( + (id: string, phase: string, actualDuration: number) => { + startAndEndSpan("widgetRender", Date.now(), actualDuration, { + widgetType: type, + // mount or update phase + phase, + }); + }, + [type], + ); + return ( + + {children} + + ); +}; diff --git a/app/client/src/widgets/BaseWidgetHOC/withBaseWidgetHOC.ts b/app/client/src/widgets/BaseWidgetHOC/withBaseWidgetHOC.ts index b37a01a3ec..454a91c054 100644 --- a/app/client/src/widgets/BaseWidgetHOC/withBaseWidgetHOC.ts +++ b/app/client/src/widgets/BaseWidgetHOC/withBaseWidgetHOC.ts @@ -3,7 +3,6 @@ import withMeta from "widgets/MetaHOC"; import { withLazyRender } from "widgets/withLazyRender"; import type BaseWidget from "widgets/BaseWidget"; import withWidgetProps from "widgets/withWidgetProps"; -import * as Sentry from "@sentry/react"; import { withLayoutSystemWidgetHOC } from "../../layoutSystems/withLayoutSystemWidgetHOC"; import { flow, identity } from "lodash"; @@ -26,8 +25,5 @@ export const withBaseWidgetHOC = ( // Adds/Enhances widget props withWidgetProps, - - // Wraps the widget to be profiled via sentry - Sentry.withProfiler, ])(Widget); }; diff --git a/app/client/src/widgets/withWidgetProps.tsx b/app/client/src/widgets/withWidgetProps.tsx index 991d38171d..0abe1b3806 100644 --- a/app/client/src/widgets/withWidgetProps.tsx +++ b/app/client/src/widgets/withWidgetProps.tsx @@ -49,6 +49,9 @@ import { getLayoutSystemType } from "selectors/layoutSystemSelectors"; import { isWidgetSelectedForPropertyPane } from "selectors/propertyPaneSelectors"; import WidgetFactory from "WidgetProvider/factory"; import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; +import { WidgetProfiler } from "./BaseWidgetHOC/WidgetProfiler"; +import { getAppsmithConfigs } from "@appsmith/configs"; +const { newRelic } = getAppsmithConfigs(); const WIDGETS_WITH_CHILD_WIDGETS = ["LIST_WIDGET", "FORM_WIDGET"]; const WIDGETS_REQUIRING_SELECTED_ANCESTRY = ["MODAL_WIDGET", "TABS_WIDGET"]; @@ -353,7 +356,15 @@ function withWidgetProps(WrappedWidget: typeof BaseWidget) { } } - return ; + if (!newRelic.enableNewRelic) { + return ; + } + + return ( + + + + ); } return WrappedPropsComponent;