diff --git a/.changeset/salty-streets-ring.md b/.changeset/salty-streets-ring.md
new file mode 100644
index 0000000..ba1875d
--- /dev/null
+++ b/.changeset/salty-streets-ring.md
@@ -0,0 +1,5 @@
+---
+"react-native-open-telemetry": minor
+---
+
+sessions: trace correlation based on the session.id attribute
diff --git a/example/src/App.tsx b/example/src/App.tsx
index affcdcd..21926f5 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -8,6 +8,11 @@ const sdk = openTelemetrySDK({
name: "MyExampleApp",
version: "1.0.0-alpha",
environment: "development",
+ features: {
+ session: {
+ getSessionId: () => "custom-session-id",
+ },
+ },
});
const tracer = sdk.trace.getTracer("my-js-tracer");
@@ -78,8 +83,8 @@ export default function App() {
onPress={() => {
fetch("https://api.weatherstack.com/current?query=Portland")
.then((response) => response.json())
- .then(data => console.log(data))
- .catch(error => console.error(error))
+ .then((data) => console.log(data))
+ .catch((error) => console.error(error));
}}
>
Fetch weather
diff --git a/src/SessionIdProcessor.ts b/src/SessionIdProcessor.ts
new file mode 100644
index 0000000..29b6067
--- /dev/null
+++ b/src/SessionIdProcessor.ts
@@ -0,0 +1,32 @@
+import type { Context } from "@opentelemetry/api";
+import type {
+ Span,
+ SpanProcessor,
+ ReadableSpan,
+} from "@opentelemetry/sdk-trace-base";
+
+type GetSessionId = () => string | null;
+
+export class SessionIdProcessor implements SpanProcessor {
+ getSessionId: GetSessionId;
+
+ constructor(getSessionId: GetSessionId) {
+ this.getSessionId = getSessionId;
+ }
+
+ onStart(span: Span, _parentContext: Context): void {
+ const sessionId = this.getSessionId();
+ if (!sessionId) return;
+ span.setAttribute("session.id", sessionId);
+ }
+
+ onEnd(_span: ReadableSpan): void {}
+
+ forceFlush(): Promise {
+ return Promise.resolve();
+ }
+
+ shutdown(): Promise {
+ return Promise.resolve();
+ }
+}
diff --git a/src/index.tsx b/src/index.tsx
index 55427ae..c27040c 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -27,6 +27,7 @@ import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
} from "@opentelemetry/semantic-conventions";
+import { SessionIdProcessor } from "./SessionIdProcessor";
import type { Options } from "./types";
export function openTelemetrySDK(options: Options = {}) {
@@ -60,12 +61,16 @@ export function openTelemetrySDK(options: Options = {}) {
})
)
: null;
+ const sessionSpanProcessor = options.features?.session
+ ? new SessionIdProcessor(options.features.session.getSessionId)
+ : null;
const tracerProvider = new WebTracerProvider({
resource,
spanProcessors: [
logSpanProcessor,
otlpSpanProcessor,
+ sessionSpanProcessor,
].filter((processor) => processor !== null),
});
@@ -84,8 +89,8 @@ export function openTelemetrySDK(options: Options = {}) {
propagateTraceHeaderCorsUrls: /.*/,
clearTimingResources: false,
}),
- ]
- })
+ ],
+ });
// Metrics
diff --git a/src/types.ts b/src/types.ts
index 13d2f23..18e87a3 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -5,4 +5,9 @@ export interface Options {
url?: string;
debug?: boolean;
native?: boolean;
+ features?: {
+ session?: {
+ getSessionId: () => string | null;
+ };
+ };
}