Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 34 additions & 16 deletions app/client/src/UITelemetry/PageLoadInstrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,23 @@ import type {
} from "web-vitals";
import isString from "lodash/isString";

type TNavigator = Navigator & {
deviceMemory: number;
connection: {
effectiveType: string;
downlink: number;
rtt: number;
saveData: boolean;
};
};

export class PageLoadInstrumentation extends InstrumentationBase {
// PerformanceObserver to observe resource timings
resourceTimingObserver: PerformanceObserver | null = null;
// Root span for the page load instrumentation
rootSpan: Span;
// List of resource URLs to ignore
ignoreResourceUrls: string[] = [];
// Timestamp when the page was last hidden
pageLastHiddenAt: number = 0;
// Duration the page was hidden for
pageHiddenFor: number = 0;
// Flag to check if navigation entry was pushed
wasNavigationEntryPushed: boolean = false;
// Set to keep track of resource entries
Expand All @@ -44,7 +50,11 @@ export class PageLoadInstrumentation extends InstrumentationBase {
}

enable(): void {
this.addVisibilityChangeListener();
// Register connection change listener
this.addConnectionAttributes();

// Add device attributes to the root span
this.addDeviceAttributes();

// Listen for LCP and FCP events
// reportAllChanges: true will report all LCP and FCP events
Expand All @@ -61,19 +71,28 @@ export class PageLoadInstrumentation extends InstrumentationBase {
}
}

private addVisibilityChangeListener() {
// Listen for page visibility changes to track time spent on hidden page
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") {
this.pageLastHiddenAt = performance.now();
} else {
const endTime = performance.now();

this.pageHiddenFor = endTime - this.pageLastHiddenAt;
}
private addDeviceAttributes() {
this.rootSpan.setAttributes({
deviceMemory: (navigator as TNavigator).deviceMemory,
hardwareConcurrency: navigator.hardwareConcurrency,
});
}

private addConnectionAttributes() {
if ((navigator as TNavigator).connection) {
const { downlink, effectiveType, rtt, saveData } = (
navigator as TNavigator
).connection;

this.rootSpan.setAttributes({
effectiveConnectionType: effectiveType,
connectionDownlink: downlink,
connectionRtt: rtt,
connectionSaveData: saveData,
});
}
}

// Handler for LCP report
private onLCPReport(metric: LCPMetricWithAttribution) {
const {
Expand Down Expand Up @@ -156,7 +175,6 @@ export class PageLoadInstrumentation extends InstrumentationBase {
element: this.getElementName(element),
entryType,
loadTime,
pageHiddenFor: this.pageHiddenFor,
},
0,
);
Expand Down
12 changes: 10 additions & 2 deletions app/client/src/UITelemetry/generateTraces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import type {
import { SpanKind } from "@opentelemetry/api";
import { context } from "@opentelemetry/api";
import { trace } from "@opentelemetry/api";
import { deviceType, browserName, browserVersion } from "react-device-detect";
import {
deviceType,
browserName,
browserVersion,
osName,
osVersion,
} from "react-device-detect";
import { APP_MODE } from "entities/App";
import { matchBuilderPath, matchViewerPath } from "constants/routes";
import nanoid from "nanoid";
Expand All @@ -33,7 +39,7 @@ const getAppMode = memoizeOne((pathname: string) => {
return appMode;
});

const getCommonTelemetryAttributes = () => {
export const getCommonTelemetryAttributes = () => {
const pathname = window.location.pathname;
const appMode = getAppMode(pathname);

Expand All @@ -44,6 +50,8 @@ const getCommonTelemetryAttributes = () => {
browserVersion,
otlpSessionId: OTLP_SESSION_ID,
hostname: window.location.hostname,
osName,
osVersion,
};
};

Expand Down
8 changes: 7 additions & 1 deletion app/client/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { getAppsmithConfigs } from "ee/configs";
import { PageViewTiming } from "@newrelic/browser-agent/features/page_view_timing";
import { PageViewEvent } from "@newrelic/browser-agent/features/page_view_event";
import { Agent } from "@newrelic/browser-agent/loaders/agent";
import { getCommonTelemetryAttributes } from "UITelemetry/generateTraces";

const { newRelic } = getAppsmithConfigs();
const { enableNewRelic } = newRelic;
Expand Down Expand Up @@ -56,7 +57,7 @@ const newRelicBrowserAgentConfig = {

// The agent loader code executes immediately on instantiation.
if (enableNewRelic) {
new Agent(
const newRelicBrowserAgent = new Agent(
{
...newRelicBrowserAgentConfig,
features: [PageViewTiming, PageViewEvent],
Expand All @@ -65,6 +66,11 @@ if (enableNewRelic) {
// Passing a null value throws an error as well. So we pass undefined.
undefined,
);

const { appMode, otlpSessionId } = getCommonTelemetryAttributes();

newRelicBrowserAgent.setCustomAttribute("otlpSessionId", otlpSessionId);
newRelicBrowserAgent.setCustomAttribute("appMode", appMode);
}

const shouldAutoFreeze = process.env.NODE_ENV === "development";
Expand Down