Skip to content
Open
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
21 changes: 11 additions & 10 deletions app/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,18 @@
"@github/g-emoji-element": "^1.1.5",
"@googlemaps/markerclusterer": "^2.0.14",
"@googlemaps/react-wrapper": "^1.1.35",
"@grafana/faro-react": "^1.12.2",
"@grafana/faro-web-tracing": "^1.12.2",
"@grafana/faro-react": "^2.0.2",
"@grafana/faro-web-tracing": "^2.0.2",
"@manaflair/redux-batch": "^1.0.0",
"@mantine/hooks": "^5.10.1",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/context-zone": "^1.30.0",
"@opentelemetry/core": "^1.30.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
"@opentelemetry/instrumentation": "^0.57.0",
"@opentelemetry/resources": "^1.30.0",
"@opentelemetry/sdk-trace-base": "^1.30.0",
"@opentelemetry/sdk-trace-web": "^1.30.0",
"@opentelemetry/context-zone": "^2.8.0",
"@opentelemetry/core": "^2.8.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.220.0",
"@opentelemetry/instrumentation": "^0.220.0",
"@opentelemetry/resources": "^2.8.0",
"@opentelemetry/sdk-trace-base": "^2.8.0",
"@opentelemetry/sdk-trace-web": "^2.8.0",
"@opentelemetry/semantic-conventions": "^1.28.0",
"@react-spring/web": "^9.7.4",
"@react-types/shared": "^3.23.0",
Expand Down Expand Up @@ -489,6 +489,7 @@
"launch-editor": "2.14.1",
"@babel/core": "7.29.6",
"http-proxy-middleware": "2.0.10",
"ws": "^8.21.0"
"ws": "^8.21.0",
"@opentelemetry/core": "^2.8.0"
}
}
72 changes: 55 additions & 17 deletions app/client/src/instrumentation/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
import type {
Span,
SpanProcessor,
ReadableSpan,
} from "@opentelemetry/sdk-trace-web";
import type { Context } from "@opentelemetry/api";
import { trace, context } from "@opentelemetry/api";
import { Resource } from "@opentelemetry/resources";
import { resourceFromAttributes } from "@opentelemetry/resources";
import {
ATTR_DEPLOYMENT_NAME,
ATTR_SERVICE_INSTANCE_ID,
} from "@opentelemetry/semantic-conventions/incubating";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
ATTR_SERVICE_NAME,
} from "@opentelemetry/semantic-conventions";
import { getAppsmithConfigs } from "ee/configs";
import {
initializeFaro,
Expand All @@ -16,16 +21,50 @@ import {
InternalLoggerLevel,
LogLevel,
} from "@grafana/faro-react";
import {
FaroTraceExporter,
FaroSessionSpanProcessor,
} from "@grafana/faro-web-tracing";
import { FaroTraceExporter } from "@grafana/faro-web-tracing";
import log from "loglevel";
import { isTracingEnabled } from "instrumentation/utils";
import { v4 as uuidv4 } from "uuid";
import { error as errorLogger } from "loglevel";
import type { User } from "constants/userConstants";

const ATTR_DEPLOYMENT_NAME = "deployment.name" as const;
const ATTR_SESSION_ID = "session.id" as const;

/**
* Attaches only the Faro session ID to each span.
* Unlike FaroMetaAttributesSpanProcessor, this deliberately omits user PII
* (email, username, id) to avoid exporting personal data on every span.
*/
class SessionOnlySpanProcessor implements SpanProcessor {
constructor(
private processor: SpanProcessor,
private metas: Faro["metas"],
) {}

onStart(span: Span, parentContext: Context): void {
const session = this.metas.value.session;

if (session?.id) {
span.attributes[ATTR_SESSION_ID] = session.id;
}

this.processor.onStart(span, parentContext);
}

onEnd(span: ReadableSpan): void {
this.processor.onEnd(span);
}

async forceFlush(): Promise<void> {
return this.processor.forceFlush();
}

async shutdown(): Promise<void> {
return this.processor.shutdown();
}
}

class AppsmithTelemetry {
private faro: Faro | null;
private ignoreUrls = ["smartlook.cloud"];
Expand Down Expand Up @@ -63,7 +102,6 @@ class AppsmithTelemetry {
],
},
trackResources: true,
trackWebVitalsAttribution: true,
internalLoggerLevel: this.internalLoggerLevel,
sessionTracking: {
generateSessionId: () => {
Expand All @@ -75,20 +113,20 @@ class AppsmithTelemetry {
});

const tracerProvider = new WebTracerProvider({
resource: new Resource({
resource: resourceFromAttributes({
[ATTR_DEPLOYMENT_NAME]: deploymentName,
[ATTR_SERVICE_INSTANCE_ID]: serviceInstanceId,
[ATTR_SERVICE_NAME]: serviceName,
}),
spanProcessors: [
new SessionOnlySpanProcessor(
new BatchSpanProcessor(new FaroTraceExporter({ ...this.faro })),
this.faro.metas,
),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
],
});

tracerProvider.addSpanProcessor(
new FaroSessionSpanProcessor(
new BatchSpanProcessor(new FaroTraceExporter({ ...this.faro })),
this.faro.metas,
),
);

tracerProvider.register();
this.faro.api.initOTEL(trace, context);
} else {
this.faro = null;
Expand Down
Loading
Loading