@potipher/otel-react 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,13 +4,13 @@ OpenTelemetry instrumentation for React components with business analytics and e
4
4
 
5
5
  ## Features
6
6
 
7
- - 🔍 **Component Tracing** - Track clicks, changes, focus/blur events automatically
8
- - 📊 **Business Analytics** - Track custom events (purchases, signups, conversions)
9
- - 🚨 **Error Tracking** - Manual error capture with context and metadata
10
- - 📈 **Session Management** - Automatic 30-minute session tracking
11
- - 🎯 **Jaeger Integration** - View traces in Jaeger UI
12
- - 📉 **Prometheus Metrics** - Auto-convert traces to metrics
13
- - ⚡ **Zero Config** - Works out of the box with Next.js
7
+ - Component Tracing - Track clicks, changes, focus/blur events automatically
8
+ - Business Analytics - Track custom events (purchases, signups, conversions)
9
+ - Error Tracking - Manual error capture with context and metadata
10
+ - Session Management - Automatic 30-minute session tracking
11
+ - Jaeger Integration - View traces in Jaeger UI
12
+ - Prometheus Metrics - Auto-convert traces to metrics
13
+ - Zero Config - Works out of the box with Next.js
14
14
 
15
15
  ## Installation
16
16
 
@@ -60,7 +60,7 @@ export default function RootLayout({ children }) {
60
60
  }
61
61
  ```
62
62
 
63
- ### 3. Create API Proxy (for self-hosting)
63
+ ### 3. Create API Proxy
64
64
 
65
65
  Create `/app/api/traces/route.ts`:
66
66
 
@@ -185,55 +185,6 @@ function MyComponent() {
185
185
  }
186
186
  ```
187
187
 
188
- ## Self-Hosting Stack
189
-
190
- Run your own OTLP collector with Docker Compose:
191
-
192
- ```yaml
193
- services:
194
- otel-collector:
195
- image: otel/opentelemetry-collector-contrib:latest
196
- ports:
197
- - "4318:4318"
198
- volumes:
199
- - ./otel-config.yaml:/etc/otel-config.yaml
200
- command: ["--config=/etc/otel-config.yaml"]
201
-
202
- jaeger:
203
- image: jaegertracing/all-in-one:latest
204
- ports:
205
- - "16686:16686"
206
- - "14268:14268"
207
-
208
- prometheus:
209
- image: prom/prometheus:latest
210
- ports:
211
- - "9090:9090"
212
-
213
- grafana:
214
- image: grafana/grafana:latest
215
- ports:
216
- - "3001:3000"
217
- ```
218
-
219
- Then access:
220
- - Jaeger UI: http://localhost:16686
221
- - Prometheus: http://localhost:9090
222
- - Grafana: http://localhost:3001
223
-
224
- ## Hosted Solution
225
-
226
- Use Potipher's hosted infrastructure (no Docker needed):
227
-
228
- ```tsx
229
- <TracingProvider config={{
230
- serviceName: 'my-app',
231
- apiEndpoint: 'https://collector.potipher.com/v1/traces'
232
- }}>
233
- ```
234
-
235
- Access your dashboards at [potipher.com](https://potipher.com)
236
-
237
188
  ## License
238
189
 
239
190
  MIT
package/dist/index.d.mts CHANGED
@@ -100,6 +100,7 @@ declare class SessionManager {
100
100
  interface TracingConfig {
101
101
  serviceName: string;
102
102
  apiEndpoint?: string;
103
+ headers?: Record<string, string>;
103
104
  }
104
105
  declare function initializeClientTracing(config: TracingConfig): void;
105
106
 
package/dist/index.d.ts CHANGED
@@ -100,6 +100,7 @@ declare class SessionManager {
100
100
  interface TracingConfig {
101
101
  serviceName: string;
102
102
  apiEndpoint?: string;
103
+ headers?: Record<string, string>;
103
104
  }
104
105
  declare function initializeClientTracing(config: TracingConfig): void;
105
106
 
package/dist/index.js CHANGED
@@ -280,10 +280,11 @@ function initializeClientTracing(config) {
280
280
  console.log("\u{1F50D} [Client Tracing] Initializing...");
281
281
  try {
282
282
  const apiEndpoint = config.apiEndpoint || "/api/traces";
283
- const absoluteUrl = typeof window !== "undefined" ? `${window.location.origin}${apiEndpoint}` : apiEndpoint;
283
+ const isAbsoluteUrl = apiEndpoint.startsWith("http://") || apiEndpoint.startsWith("https://");
284
+ const absoluteUrl = isAbsoluteUrl ? apiEndpoint : typeof window !== "undefined" ? `${window.location.origin}${apiEndpoint}` : apiEndpoint;
284
285
  const exporter = new exporterTraceOtlpHttp.OTLPTraceExporter({
285
- url: absoluteUrl
286
- // Must be absolute URL
286
+ url: absoluteUrl,
287
+ headers: config.headers || {}
287
288
  });
288
289
  const batchProcessor = new sdkTraceBase.BatchSpanProcessor(exporter);
289
290
  const provider = new sdkTraceWeb.WebTracerProvider({
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/session.ts","../src/tracer.ts","../src/client-instrumentation.ts","../src/provider.tsx","../src/hooks.ts"],"names":["tracer","OTLPTraceExporter","BatchSpanProcessor","WebTracerProvider","Resource","ATTR_SERVICE_NAME","ZoneContextManager","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * OpenTelemetry Tracing Types\n * \n * Type definitions for component tracing and telemetry\n */\n\n// Interaction types for component events\nexport type InteractionType =\n | \"click\"\n | \"change\"\n | \"focus\"\n | \"blur\"\n | \"submit\"\n | \"open\"\n | \"close\"\n | \"select\"\n | \"search\"\n | \"render\"\n | \"mount\"\n | \"unmount\"\n | \"error\"\n | \"custom\"\n\n// Component status codes (aligned with HTTP status codes)\nexport const ComponentStatus = {\n OK: 200,\n ERROR: 500,\n VALIDATION_ERROR: 400,\n NOT_FOUND: 404,\n} as const\n\nexport type ComponentStatusCode =\n (typeof ComponentStatus)[keyof typeof ComponentStatus]\n\n// Trace attributes for components\nexport interface ComponentTraceAttributes {\n \"component.name\": string\n \"component.type\": string\n \"component.interaction\": InteractionType\n \"component.status\": ComponentStatusCode\n \"component.props\"?: Record<string, unknown>\n \"component.error\"?: string\n \"component.duration_ms\"?: number\n \"user.action\"?: string\n [key: string]: unknown\n}\n\n// Trace event for components\nexport interface ComponentTraceEvent {\n name: string\n timestamp: number\n attributes: ComponentTraceAttributes\n status: ComponentStatusCode\n}\n\n// Configuration for traced components\nexport interface TraceConfig {\n enabled: boolean\n sampleRate: number // 0.0 to 1.0\n captureProps: boolean\n captureErrors: boolean\n destinations: (\"otlp\" | \"console\" | \"custom\")[]\n}\n","/**\n * Session Management for Tracing\n * \n * Manages user session IDs with 30-minute timeout\n */\n\nconst SESSION_KEY = \"tracing_session_id\"\nconst SESSION_TIMEOUT = 30 * 60 * 1000 // 30 minutes in milliseconds\n\ninterface SessionData {\n id: string\n lastActivity: number\n}\n\nexport class SessionManager {\n /**\n * Get or create a session ID\n */\n static getSessionId(): string {\n if (typeof window === \"undefined\") {\n return \"server-side\"\n }\n\n try {\n const storedData = localStorage.getItem(SESSION_KEY)\n\n if (storedData) {\n const sessionData: SessionData = JSON.parse(storedData)\n const now = Date.now()\n\n // Check if session has expired\n if (now - sessionData.lastActivity < SESSION_TIMEOUT) {\n // Update last activity\n sessionData.lastActivity = now\n localStorage.setItem(SESSION_KEY, JSON.stringify(sessionData))\n return sessionData.id\n }\n }\n\n // Create new session\n const newSessionId = this.generateSessionId()\n const newSessionData: SessionData = {\n id: newSessionId,\n lastActivity: Date.now(),\n }\n localStorage.setItem(SESSION_KEY, JSON.stringify(newSessionData))\n return newSessionId\n } catch (error) {\n // Fallback if localStorage is not available\n console.warn(\"Failed to access localStorage for session management:\", error)\n return this.generateSessionId()\n }\n }\n\n /**\n * Generate a unique session ID\n */\n private static generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`\n }\n\n /**\n * Clear the current session\n */\n static clearSession(): void {\n if (typeof window !== \"undefined\") {\n try {\n localStorage.removeItem(SESSION_KEY)\n } catch (error) {\n console.warn(\"Failed to clear session:\", error)\n }\n }\n }\n}\n","/**\n * Component Tracer\n * \n * Core tracing functionality for UI components using OpenTelemetry\n */\n\nimport type {\n ComponentStatusCode,\n ComponentTraceAttributes,\n InteractionType,\n} from \"./types\"\nimport { ComponentStatus } from \"./types\"\nimport { SessionManager } from \"./session\"\n\n// Lazy-load OpenTelemetry to avoid bundle bloat\nlet tracer: any = null\n\nasync function getTracer() {\n if (tracer) return tracer\n\n if (typeof window === \"undefined\") {\n // Server-side: return a no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n\n try {\n // Dynamically import OpenTelemetry (only in browser)\n const { trace } = await import(\"@opentelemetry/api\")\n tracer = trace.getTracer(\"component-tracer\")\n return tracer\n } catch (error) {\n console.warn(\"OpenTelemetry not available, tracing disabled:\", error)\n // Return no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n}\n\nexport class ComponentTracer {\n /**\n * Record a component interaction\n */\n static async recordInteraction(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {},\n statusCode: ComponentStatusCode = ComponentStatus.OK\n ): Promise<void> {\n const tracer = await getTracer()\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1, // INTERNAL\n startTime: Date.now(),\n })\n\n // Auto-capture current page from URL\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n\n // Get session ID\n const sessionId = SessionManager.getSessionId()\n\n // Set component attributes\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.status\": statusCode,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: (attributes[\"page\"] as string) || currentPage,\n \"session.id\": sessionId,\n })\n\n // Add all additional attributes\n Object.entries(attributes).forEach(([key, value]) => {\n // Skip already set attributes and complex objects\n if (\n key === \"component.name\" ||\n key === \"component.interaction\" ||\n key === \"component.status\" ||\n key === \"component.type\" ||\n key === \"page\" ||\n key === \"session.id\"\n ) {\n return\n }\n\n // Only add primitive values (string, number, boolean)\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set status\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2, // OK = 1, ERROR = 2\n })\n\n // End span\n span.end()\n }\n\n /**\n * Start a long-running operation (e.g., form submission)\n * Returns an operation ID that can be used to end the operation\n */\n static async startOperation(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<string> {\n const tracer = await getTracer()\n const operationId = `${componentName}_${interaction}_${Date.now()}`\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1,\n startTime: Date.now(),\n })\n\n // Store span for later retrieval\n if (typeof window !== \"undefined\") {\n ;(window as any).__activeSpans = (window as any).__activeSpans || {}\n ;(window as any).__activeSpans[operationId] = span\n }\n\n // Set initial attributes\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n const sessionId = SessionManager.getSessionId()\n\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: currentPage,\n \"session.id\": sessionId,\n ...attributes,\n })\n\n return operationId\n }\n\n /**\n * End a long-running operation\n */\n static async endOperation(\n operationId: string,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n additionalAttributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const span = (window as any).__activeSpans?.[operationId]\n if (!span) {\n console.warn(`No active span found for operation: ${operationId}`)\n return\n }\n\n // Add final attributes\n Object.entries(additionalAttributes).forEach(([key, value]) => {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set final status\n span.setAttribute(\"component.status\", statusCode)\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2,\n })\n\n span.end()\n\n // Clean up\n delete (window as any).__activeSpans[operationId]\n }\n\n /**\n * Capture a custom error manually\n * @param error - The error object or message\n * @param context - Additional context about the error\n */\n static async captureError(\n error: Error | string,\n context?: {\n componentName?: string;\n userId?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(\"error.captured\", {\n attributes: {\n \"component.type\": \"error\",\n \"interaction.type\": \"error\",\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add error details\n const errorMessage = error instanceof Error ? error.message : error\n const errorStack = error instanceof Error ? error.stack : undefined\n\n span.setAttribute(\"error\", true)\n span.setAttribute(\"error.message\", errorMessage)\n if (errorStack) {\n span.setAttribute(\"error.stack\", errorStack)\n }\n\n // Add context\n if (context?.componentName) {\n span.setAttribute(\"component.name\", context.componentName)\n }\n if (context?.userId) {\n span.setAttribute(\"user.id\", context.userId)\n }\n if (context?.metadata) {\n Object.entries(context.metadata).forEach(([key, value]) => {\n span.setAttribute(`error.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set error status\n span.setAttribute(\"component.status\", ComponentStatus.ERROR)\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: errorMessage,\n })\n\n span.end()\n\n console.log(`[ComponentTracer] Captured error: ${errorMessage}`)\n }\n\n /**\n * Track a custom business event\n * @param eventName - Name of the event (e.g., 'purchase_completed', 'user_signup')\n * @param properties - Event properties/metadata\n */\n static async trackEvent(\n eventName: string,\n properties?: {\n componentName?: string;\n userId?: string;\n value?: number;\n currency?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(eventName, {\n attributes: {\n \"component.type\": \"custom-event\",\n \"interaction.type\": \"custom\",\n \"event.name\": eventName,\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add properties\n if (properties?.componentName) {\n span.setAttribute(\"component.name\", properties.componentName)\n }\n if (properties?.userId) {\n span.setAttribute(\"user.id\", properties.userId)\n }\n if (properties?.value !== undefined) {\n span.setAttribute(\"event.value\", properties.value)\n }\n if (properties?.currency) {\n span.setAttribute(\"event.currency\", properties.currency)\n }\n if (properties?.metadata) {\n Object.entries(properties.metadata).forEach(([key, value]) => {\n span.setAttribute(`event.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set success status\n span.setAttribute(\"component.status\", ComponentStatus.OK)\n span.setStatus({ code: 1 }) // SpanStatusCode.OK\n\n span.end()\n\n console.log(`[ComponentTracer] Tracked event: ${eventName}`, properties)\n }\n}\n","\"use client\"\n\n/**\n * Client-side OpenTelemetry Instrumentation\n * \n * Initializes OTEL in the browser to send component traces to the collector\n */\n\nimport { WebTracerProvider } from \"@opentelemetry/sdk-trace-web\"\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport { ZoneContextManager } from \"@opentelemetry/context-zone\"\nimport { Resource } from \"@opentelemetry/resources\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\n\nlet isInitialized = false\n\nexport interface TracingConfig {\n serviceName: string\n apiEndpoint?: string // Default: /api/traces\n}\n\nexport function initializeClientTracing(config: TracingConfig) {\n // Only initialize once\n if (isInitialized || typeof window === \"undefined\") {\n return\n }\n\n console.log(\"🔍 [Client Tracing] Initializing...\")\n\n try {\n // Build absolute URL for the API endpoint\n const apiEndpoint = config.apiEndpoint || \"/api/traces\"\n const absoluteUrl = typeof window !== \"undefined\" \n ? `${window.location.origin}${apiEndpoint}`\n : apiEndpoint\n\n // Configure OTLP exporter to use Next.js API proxy (avoids CORS)\n const exporter = new OTLPTraceExporter({\n url: absoluteUrl, // Must be absolute URL\n })\n\n // Create batch processor\n const batchProcessor = new BatchSpanProcessor(exporter)\n\n // Create tracer provider with service name\n const provider = new WebTracerProvider({\n resource: new Resource({\n [ATTR_SERVICE_NAME]: config.serviceName,\n }),\n spanProcessors: [batchProcessor],\n })\n\n // Register the provider\n provider.register({\n contextManager: new ZoneContextManager(),\n })\n\n isInitialized = true\n console.log(\"✅ [Client Tracing] Initialized successfully\")\n console.log(`📍 Service: ${config.serviceName}`)\n console.log(`📍 Endpoint: ${absoluteUrl}`)\n } catch (error) {\n console.error(\"❌ [Client Tracing] Failed to initialize:\", error)\n }\n}\n","\"use client\"\n\n/**\n * TracingProvider Component\n * \n * Initializes OpenTelemetry tracing on the client side\n * Wrap your app with this provider to enable tracing\n */\n\nimport { useEffect, type ReactNode } from \"react\"\nimport { initializeClientTracing, type TracingConfig } from \"./client-instrumentation\"\n\ninterface TracingProviderProps {\n children?: ReactNode\n config: TracingConfig\n}\n\nexport function TracingProvider({ children, config }: TracingProviderProps) {\n useEffect(() => {\n initializeClientTracing(config)\n }, [config])\n\n return <>{children}</>\n}\n","\"use client\"\n\n/**\n * React Hooks for Component Tracing\n * \n * Provides easy-to-use hooks for tracing component interactions\n */\n\nimport { useCallback, useEffect } from \"react\"\nimport { ComponentTracer } from \"./tracer\"\nimport { ComponentStatus } from \"./types\"\nimport type { InteractionType, ComponentStatusCode } from \"./types\"\n\n/**\n * Hook for tracing component interactions\n */\nexport function useComponentTrace(componentName: string) {\n // Record component mount\n useEffect(() => {\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"mount\")\n }\n\n return () => {\n // Record component unmount\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"unmount\")\n }\n }\n }, [componentName])\n\n // Click tracking\n const recordClick = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"click\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Change tracking\n const recordChange = useCallback(\n (\n value: unknown,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"change\",\n {\n \"component.value\": typeof value === \"string\" ? value : String(value),\n ...metadata,\n },\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Focus tracking\n const recordFocus = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"focus\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Blur tracking\n const recordBlur = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"blur\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Custom interaction tracking\n const recordCustom = useCallback(\n (\n interaction: InteractionType,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n interaction,\n metadata || {},\n statusCode\n )\n },\n [componentName]\n )\n\n return {\n recordClick,\n recordChange,\n recordFocus,\n recordBlur,\n recordCustom,\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/session.ts","../src/tracer.ts","../src/client-instrumentation.ts","../src/provider.tsx","../src/hooks.ts"],"names":["tracer","OTLPTraceExporter","BatchSpanProcessor","WebTracerProvider","Resource","ATTR_SERVICE_NAME","ZoneContextManager","useEffect","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * OpenTelemetry Tracing Types\n * \n * Type definitions for component tracing and telemetry\n */\n\n// Interaction types for component events\nexport type InteractionType =\n | \"click\"\n | \"change\"\n | \"focus\"\n | \"blur\"\n | \"submit\"\n | \"open\"\n | \"close\"\n | \"select\"\n | \"search\"\n | \"render\"\n | \"mount\"\n | \"unmount\"\n | \"error\"\n | \"custom\"\n\n// Component status codes (aligned with HTTP status codes)\nexport const ComponentStatus = {\n OK: 200,\n ERROR: 500,\n VALIDATION_ERROR: 400,\n NOT_FOUND: 404,\n} as const\n\nexport type ComponentStatusCode =\n (typeof ComponentStatus)[keyof typeof ComponentStatus]\n\n// Trace attributes for components\nexport interface ComponentTraceAttributes {\n \"component.name\": string\n \"component.type\": string\n \"component.interaction\": InteractionType\n \"component.status\": ComponentStatusCode\n \"component.props\"?: Record<string, unknown>\n \"component.error\"?: string\n \"component.duration_ms\"?: number\n \"user.action\"?: string\n [key: string]: unknown\n}\n\n// Trace event for components\nexport interface ComponentTraceEvent {\n name: string\n timestamp: number\n attributes: ComponentTraceAttributes\n status: ComponentStatusCode\n}\n\n// Configuration for traced components\nexport interface TraceConfig {\n enabled: boolean\n sampleRate: number // 0.0 to 1.0\n captureProps: boolean\n captureErrors: boolean\n destinations: (\"otlp\" | \"console\" | \"custom\")[]\n}\n","/**\n * Session Management for Tracing\n * \n * Manages user session IDs with 30-minute timeout\n */\n\nconst SESSION_KEY = \"tracing_session_id\"\nconst SESSION_TIMEOUT = 30 * 60 * 1000 // 30 minutes in milliseconds\n\ninterface SessionData {\n id: string\n lastActivity: number\n}\n\nexport class SessionManager {\n /**\n * Get or create a session ID\n */\n static getSessionId(): string {\n if (typeof window === \"undefined\") {\n return \"server-side\"\n }\n\n try {\n const storedData = localStorage.getItem(SESSION_KEY)\n\n if (storedData) {\n const sessionData: SessionData = JSON.parse(storedData)\n const now = Date.now()\n\n // Check if session has expired\n if (now - sessionData.lastActivity < SESSION_TIMEOUT) {\n // Update last activity\n sessionData.lastActivity = now\n localStorage.setItem(SESSION_KEY, JSON.stringify(sessionData))\n return sessionData.id\n }\n }\n\n // Create new session\n const newSessionId = this.generateSessionId()\n const newSessionData: SessionData = {\n id: newSessionId,\n lastActivity: Date.now(),\n }\n localStorage.setItem(SESSION_KEY, JSON.stringify(newSessionData))\n return newSessionId\n } catch (error) {\n // Fallback if localStorage is not available\n console.warn(\"Failed to access localStorage for session management:\", error)\n return this.generateSessionId()\n }\n }\n\n /**\n * Generate a unique session ID\n */\n private static generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`\n }\n\n /**\n * Clear the current session\n */\n static clearSession(): void {\n if (typeof window !== \"undefined\") {\n try {\n localStorage.removeItem(SESSION_KEY)\n } catch (error) {\n console.warn(\"Failed to clear session:\", error)\n }\n }\n }\n}\n","/**\n * Component Tracer\n * \n * Core tracing functionality for UI components using OpenTelemetry\n */\n\nimport type {\n ComponentStatusCode,\n ComponentTraceAttributes,\n InteractionType,\n} from \"./types\"\nimport { ComponentStatus } from \"./types\"\nimport { SessionManager } from \"./session\"\n\n// Lazy-load OpenTelemetry to avoid bundle bloat\nlet tracer: any = null\n\nasync function getTracer() {\n if (tracer) return tracer\n\n if (typeof window === \"undefined\") {\n // Server-side: return a no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n\n try {\n // Dynamically import OpenTelemetry (only in browser)\n const { trace } = await import(\"@opentelemetry/api\")\n tracer = trace.getTracer(\"component-tracer\")\n return tracer\n } catch (error) {\n console.warn(\"OpenTelemetry not available, tracing disabled:\", error)\n // Return no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n}\n\nexport class ComponentTracer {\n /**\n * Record a component interaction\n */\n static async recordInteraction(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {},\n statusCode: ComponentStatusCode = ComponentStatus.OK\n ): Promise<void> {\n const tracer = await getTracer()\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1, // INTERNAL\n startTime: Date.now(),\n })\n\n // Auto-capture current page from URL\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n\n // Get session ID\n const sessionId = SessionManager.getSessionId()\n\n // Set component attributes\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.status\": statusCode,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: (attributes[\"page\"] as string) || currentPage,\n \"session.id\": sessionId,\n })\n\n // Add all additional attributes\n Object.entries(attributes).forEach(([key, value]) => {\n // Skip already set attributes and complex objects\n if (\n key === \"component.name\" ||\n key === \"component.interaction\" ||\n key === \"component.status\" ||\n key === \"component.type\" ||\n key === \"page\" ||\n key === \"session.id\"\n ) {\n return\n }\n\n // Only add primitive values (string, number, boolean)\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set status\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2, // OK = 1, ERROR = 2\n })\n\n // End span\n span.end()\n }\n\n /**\n * Start a long-running operation (e.g., form submission)\n * Returns an operation ID that can be used to end the operation\n */\n static async startOperation(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<string> {\n const tracer = await getTracer()\n const operationId = `${componentName}_${interaction}_${Date.now()}`\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1,\n startTime: Date.now(),\n })\n\n // Store span for later retrieval\n if (typeof window !== \"undefined\") {\n ;(window as any).__activeSpans = (window as any).__activeSpans || {}\n ;(window as any).__activeSpans[operationId] = span\n }\n\n // Set initial attributes\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n const sessionId = SessionManager.getSessionId()\n\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: currentPage,\n \"session.id\": sessionId,\n ...attributes,\n })\n\n return operationId\n }\n\n /**\n * End a long-running operation\n */\n static async endOperation(\n operationId: string,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n additionalAttributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const span = (window as any).__activeSpans?.[operationId]\n if (!span) {\n console.warn(`No active span found for operation: ${operationId}`)\n return\n }\n\n // Add final attributes\n Object.entries(additionalAttributes).forEach(([key, value]) => {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set final status\n span.setAttribute(\"component.status\", statusCode)\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2,\n })\n\n span.end()\n\n // Clean up\n delete (window as any).__activeSpans[operationId]\n }\n\n /**\n * Capture a custom error manually\n * @param error - The error object or message\n * @param context - Additional context about the error\n */\n static async captureError(\n error: Error | string,\n context?: {\n componentName?: string;\n userId?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(\"error.captured\", {\n attributes: {\n \"component.type\": \"error\",\n \"interaction.type\": \"error\",\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add error details\n const errorMessage = error instanceof Error ? error.message : error\n const errorStack = error instanceof Error ? error.stack : undefined\n\n span.setAttribute(\"error\", true)\n span.setAttribute(\"error.message\", errorMessage)\n if (errorStack) {\n span.setAttribute(\"error.stack\", errorStack)\n }\n\n // Add context\n if (context?.componentName) {\n span.setAttribute(\"component.name\", context.componentName)\n }\n if (context?.userId) {\n span.setAttribute(\"user.id\", context.userId)\n }\n if (context?.metadata) {\n Object.entries(context.metadata).forEach(([key, value]) => {\n span.setAttribute(`error.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set error status\n span.setAttribute(\"component.status\", ComponentStatus.ERROR)\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: errorMessage,\n })\n\n span.end()\n\n console.log(`[ComponentTracer] Captured error: ${errorMessage}`)\n }\n\n /**\n * Track a custom business event\n * @param eventName - Name of the event (e.g., 'purchase_completed', 'user_signup')\n * @param properties - Event properties/metadata\n */\n static async trackEvent(\n eventName: string,\n properties?: {\n componentName?: string;\n userId?: string;\n value?: number;\n currency?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(eventName, {\n attributes: {\n \"component.type\": \"custom-event\",\n \"interaction.type\": \"custom\",\n \"event.name\": eventName,\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add properties\n if (properties?.componentName) {\n span.setAttribute(\"component.name\", properties.componentName)\n }\n if (properties?.userId) {\n span.setAttribute(\"user.id\", properties.userId)\n }\n if (properties?.value !== undefined) {\n span.setAttribute(\"event.value\", properties.value)\n }\n if (properties?.currency) {\n span.setAttribute(\"event.currency\", properties.currency)\n }\n if (properties?.metadata) {\n Object.entries(properties.metadata).forEach(([key, value]) => {\n span.setAttribute(`event.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set success status\n span.setAttribute(\"component.status\", ComponentStatus.OK)\n span.setStatus({ code: 1 }) // SpanStatusCode.OK\n\n span.end()\n\n console.log(`[ComponentTracer] Tracked event: ${eventName}`, properties)\n }\n}\n","\"use client\"\n\n/**\n * Client-side OpenTelemetry Instrumentation\n * \n * Initializes OTEL in the browser to send component traces to the collector\n */\n\nimport { WebTracerProvider } from \"@opentelemetry/sdk-trace-web\"\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport { ZoneContextManager } from \"@opentelemetry/context-zone\"\nimport { Resource } from \"@opentelemetry/resources\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\n\nlet isInitialized = false\n\nexport interface TracingConfig {\n serviceName: string\n apiEndpoint?: string // Default: /api/traces\n headers?: Record<string, string> // Custom headers (e.g., x-api-key)\n}\n\nexport function initializeClientTracing(config: TracingConfig) {\n // Only initialize once\n if (isInitialized || typeof window === \"undefined\") {\n return\n }\n\n console.log(\"🔍 [Client Tracing] Initializing...\")\n\n try {\n // Build absolute URL for the API endpoint\n const apiEndpoint = config.apiEndpoint || \"/api/traces\"\n \n // Check if it's already an absolute URL\n const isAbsoluteUrl = apiEndpoint.startsWith(\"http://\") || apiEndpoint.startsWith(\"https://\")\n const absoluteUrl = isAbsoluteUrl \n ? apiEndpoint\n : (typeof window !== \"undefined\" ? `${window.location.origin}${apiEndpoint}` : apiEndpoint)\n\n // Configure OTLP exporter with custom headers\n const exporter = new OTLPTraceExporter({\n url: absoluteUrl,\n headers: config.headers || {},\n })\n\n // Create batch processor\n const batchProcessor = new BatchSpanProcessor(exporter)\n\n // Create tracer provider with service name\n const provider = new WebTracerProvider({\n resource: new Resource({\n [ATTR_SERVICE_NAME]: config.serviceName,\n }),\n spanProcessors: [batchProcessor],\n })\n\n // Register the provider\n provider.register({\n contextManager: new ZoneContextManager(),\n })\n\n isInitialized = true\n console.log(\"✅ [Client Tracing] Initialized successfully\")\n console.log(`📍 Service: ${config.serviceName}`)\n console.log(`📍 Endpoint: ${absoluteUrl}`)\n } catch (error) {\n console.error(\"❌ [Client Tracing] Failed to initialize:\", error)\n }\n}\n","\"use client\"\n\n/**\n * TracingProvider Component\n * \n * Initializes OpenTelemetry tracing on the client side\n * Wrap your app with this provider to enable tracing\n */\n\nimport { useEffect, type ReactNode } from \"react\"\nimport { initializeClientTracing, type TracingConfig } from \"./client-instrumentation\"\n\ninterface TracingProviderProps {\n children?: ReactNode\n config: TracingConfig\n}\n\nexport function TracingProvider({ children, config }: TracingProviderProps) {\n useEffect(() => {\n initializeClientTracing(config)\n }, [config])\n\n return <>{children}</>\n}\n","\"use client\"\n\n/**\n * React Hooks for Component Tracing\n * \n * Provides easy-to-use hooks for tracing component interactions\n */\n\nimport { useCallback, useEffect } from \"react\"\nimport { ComponentTracer } from \"./tracer\"\nimport { ComponentStatus } from \"./types\"\nimport type { InteractionType, ComponentStatusCode } from \"./types\"\n\n/**\n * Hook for tracing component interactions\n */\nexport function useComponentTrace(componentName: string) {\n // Record component mount\n useEffect(() => {\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"mount\")\n }\n\n return () => {\n // Record component unmount\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"unmount\")\n }\n }\n }, [componentName])\n\n // Click tracking\n const recordClick = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"click\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Change tracking\n const recordChange = useCallback(\n (\n value: unknown,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"change\",\n {\n \"component.value\": typeof value === \"string\" ? value : String(value),\n ...metadata,\n },\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Focus tracking\n const recordFocus = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"focus\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Blur tracking\n const recordBlur = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"blur\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Custom interaction tracking\n const recordCustom = useCallback(\n (\n interaction: InteractionType,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n interaction,\n metadata || {},\n statusCode\n )\n },\n [componentName]\n )\n\n return {\n recordClick,\n recordChange,\n recordFocus,\n recordBlur,\n recordCustom,\n }\n}\n"]}
package/dist/index.mjs CHANGED
@@ -278,10 +278,11 @@ function initializeClientTracing(config) {
278
278
  console.log("\u{1F50D} [Client Tracing] Initializing...");
279
279
  try {
280
280
  const apiEndpoint = config.apiEndpoint || "/api/traces";
281
- const absoluteUrl = typeof window !== "undefined" ? `${window.location.origin}${apiEndpoint}` : apiEndpoint;
281
+ const isAbsoluteUrl = apiEndpoint.startsWith("http://") || apiEndpoint.startsWith("https://");
282
+ const absoluteUrl = isAbsoluteUrl ? apiEndpoint : typeof window !== "undefined" ? `${window.location.origin}${apiEndpoint}` : apiEndpoint;
282
283
  const exporter = new OTLPTraceExporter({
283
- url: absoluteUrl
284
- // Must be absolute URL
284
+ url: absoluteUrl,
285
+ headers: config.headers || {}
285
286
  });
286
287
  const batchProcessor = new BatchSpanProcessor(exporter);
287
288
  const provider = new WebTracerProvider({
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/session.ts","../src/tracer.ts","../src/client-instrumentation.ts","../src/provider.tsx","../src/hooks.ts"],"names":["tracer","useEffect"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * OpenTelemetry Tracing Types\n * \n * Type definitions for component tracing and telemetry\n */\n\n// Interaction types for component events\nexport type InteractionType =\n | \"click\"\n | \"change\"\n | \"focus\"\n | \"blur\"\n | \"submit\"\n | \"open\"\n | \"close\"\n | \"select\"\n | \"search\"\n | \"render\"\n | \"mount\"\n | \"unmount\"\n | \"error\"\n | \"custom\"\n\n// Component status codes (aligned with HTTP status codes)\nexport const ComponentStatus = {\n OK: 200,\n ERROR: 500,\n VALIDATION_ERROR: 400,\n NOT_FOUND: 404,\n} as const\n\nexport type ComponentStatusCode =\n (typeof ComponentStatus)[keyof typeof ComponentStatus]\n\n// Trace attributes for components\nexport interface ComponentTraceAttributes {\n \"component.name\": string\n \"component.type\": string\n \"component.interaction\": InteractionType\n \"component.status\": ComponentStatusCode\n \"component.props\"?: Record<string, unknown>\n \"component.error\"?: string\n \"component.duration_ms\"?: number\n \"user.action\"?: string\n [key: string]: unknown\n}\n\n// Trace event for components\nexport interface ComponentTraceEvent {\n name: string\n timestamp: number\n attributes: ComponentTraceAttributes\n status: ComponentStatusCode\n}\n\n// Configuration for traced components\nexport interface TraceConfig {\n enabled: boolean\n sampleRate: number // 0.0 to 1.0\n captureProps: boolean\n captureErrors: boolean\n destinations: (\"otlp\" | \"console\" | \"custom\")[]\n}\n","/**\n * Session Management for Tracing\n * \n * Manages user session IDs with 30-minute timeout\n */\n\nconst SESSION_KEY = \"tracing_session_id\"\nconst SESSION_TIMEOUT = 30 * 60 * 1000 // 30 minutes in milliseconds\n\ninterface SessionData {\n id: string\n lastActivity: number\n}\n\nexport class SessionManager {\n /**\n * Get or create a session ID\n */\n static getSessionId(): string {\n if (typeof window === \"undefined\") {\n return \"server-side\"\n }\n\n try {\n const storedData = localStorage.getItem(SESSION_KEY)\n\n if (storedData) {\n const sessionData: SessionData = JSON.parse(storedData)\n const now = Date.now()\n\n // Check if session has expired\n if (now - sessionData.lastActivity < SESSION_TIMEOUT) {\n // Update last activity\n sessionData.lastActivity = now\n localStorage.setItem(SESSION_KEY, JSON.stringify(sessionData))\n return sessionData.id\n }\n }\n\n // Create new session\n const newSessionId = this.generateSessionId()\n const newSessionData: SessionData = {\n id: newSessionId,\n lastActivity: Date.now(),\n }\n localStorage.setItem(SESSION_KEY, JSON.stringify(newSessionData))\n return newSessionId\n } catch (error) {\n // Fallback if localStorage is not available\n console.warn(\"Failed to access localStorage for session management:\", error)\n return this.generateSessionId()\n }\n }\n\n /**\n * Generate a unique session ID\n */\n private static generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`\n }\n\n /**\n * Clear the current session\n */\n static clearSession(): void {\n if (typeof window !== \"undefined\") {\n try {\n localStorage.removeItem(SESSION_KEY)\n } catch (error) {\n console.warn(\"Failed to clear session:\", error)\n }\n }\n }\n}\n","/**\n * Component Tracer\n * \n * Core tracing functionality for UI components using OpenTelemetry\n */\n\nimport type {\n ComponentStatusCode,\n ComponentTraceAttributes,\n InteractionType,\n} from \"./types\"\nimport { ComponentStatus } from \"./types\"\nimport { SessionManager } from \"./session\"\n\n// Lazy-load OpenTelemetry to avoid bundle bloat\nlet tracer: any = null\n\nasync function getTracer() {\n if (tracer) return tracer\n\n if (typeof window === \"undefined\") {\n // Server-side: return a no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n\n try {\n // Dynamically import OpenTelemetry (only in browser)\n const { trace } = await import(\"@opentelemetry/api\")\n tracer = trace.getTracer(\"component-tracer\")\n return tracer\n } catch (error) {\n console.warn(\"OpenTelemetry not available, tracing disabled:\", error)\n // Return no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n}\n\nexport class ComponentTracer {\n /**\n * Record a component interaction\n */\n static async recordInteraction(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {},\n statusCode: ComponentStatusCode = ComponentStatus.OK\n ): Promise<void> {\n const tracer = await getTracer()\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1, // INTERNAL\n startTime: Date.now(),\n })\n\n // Auto-capture current page from URL\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n\n // Get session ID\n const sessionId = SessionManager.getSessionId()\n\n // Set component attributes\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.status\": statusCode,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: (attributes[\"page\"] as string) || currentPage,\n \"session.id\": sessionId,\n })\n\n // Add all additional attributes\n Object.entries(attributes).forEach(([key, value]) => {\n // Skip already set attributes and complex objects\n if (\n key === \"component.name\" ||\n key === \"component.interaction\" ||\n key === \"component.status\" ||\n key === \"component.type\" ||\n key === \"page\" ||\n key === \"session.id\"\n ) {\n return\n }\n\n // Only add primitive values (string, number, boolean)\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set status\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2, // OK = 1, ERROR = 2\n })\n\n // End span\n span.end()\n }\n\n /**\n * Start a long-running operation (e.g., form submission)\n * Returns an operation ID that can be used to end the operation\n */\n static async startOperation(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<string> {\n const tracer = await getTracer()\n const operationId = `${componentName}_${interaction}_${Date.now()}`\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1,\n startTime: Date.now(),\n })\n\n // Store span for later retrieval\n if (typeof window !== \"undefined\") {\n ;(window as any).__activeSpans = (window as any).__activeSpans || {}\n ;(window as any).__activeSpans[operationId] = span\n }\n\n // Set initial attributes\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n const sessionId = SessionManager.getSessionId()\n\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: currentPage,\n \"session.id\": sessionId,\n ...attributes,\n })\n\n return operationId\n }\n\n /**\n * End a long-running operation\n */\n static async endOperation(\n operationId: string,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n additionalAttributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const span = (window as any).__activeSpans?.[operationId]\n if (!span) {\n console.warn(`No active span found for operation: ${operationId}`)\n return\n }\n\n // Add final attributes\n Object.entries(additionalAttributes).forEach(([key, value]) => {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set final status\n span.setAttribute(\"component.status\", statusCode)\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2,\n })\n\n span.end()\n\n // Clean up\n delete (window as any).__activeSpans[operationId]\n }\n\n /**\n * Capture a custom error manually\n * @param error - The error object or message\n * @param context - Additional context about the error\n */\n static async captureError(\n error: Error | string,\n context?: {\n componentName?: string;\n userId?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(\"error.captured\", {\n attributes: {\n \"component.type\": \"error\",\n \"interaction.type\": \"error\",\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add error details\n const errorMessage = error instanceof Error ? error.message : error\n const errorStack = error instanceof Error ? error.stack : undefined\n\n span.setAttribute(\"error\", true)\n span.setAttribute(\"error.message\", errorMessage)\n if (errorStack) {\n span.setAttribute(\"error.stack\", errorStack)\n }\n\n // Add context\n if (context?.componentName) {\n span.setAttribute(\"component.name\", context.componentName)\n }\n if (context?.userId) {\n span.setAttribute(\"user.id\", context.userId)\n }\n if (context?.metadata) {\n Object.entries(context.metadata).forEach(([key, value]) => {\n span.setAttribute(`error.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set error status\n span.setAttribute(\"component.status\", ComponentStatus.ERROR)\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: errorMessage,\n })\n\n span.end()\n\n console.log(`[ComponentTracer] Captured error: ${errorMessage}`)\n }\n\n /**\n * Track a custom business event\n * @param eventName - Name of the event (e.g., 'purchase_completed', 'user_signup')\n * @param properties - Event properties/metadata\n */\n static async trackEvent(\n eventName: string,\n properties?: {\n componentName?: string;\n userId?: string;\n value?: number;\n currency?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(eventName, {\n attributes: {\n \"component.type\": \"custom-event\",\n \"interaction.type\": \"custom\",\n \"event.name\": eventName,\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add properties\n if (properties?.componentName) {\n span.setAttribute(\"component.name\", properties.componentName)\n }\n if (properties?.userId) {\n span.setAttribute(\"user.id\", properties.userId)\n }\n if (properties?.value !== undefined) {\n span.setAttribute(\"event.value\", properties.value)\n }\n if (properties?.currency) {\n span.setAttribute(\"event.currency\", properties.currency)\n }\n if (properties?.metadata) {\n Object.entries(properties.metadata).forEach(([key, value]) => {\n span.setAttribute(`event.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set success status\n span.setAttribute(\"component.status\", ComponentStatus.OK)\n span.setStatus({ code: 1 }) // SpanStatusCode.OK\n\n span.end()\n\n console.log(`[ComponentTracer] Tracked event: ${eventName}`, properties)\n }\n}\n","\"use client\"\n\n/**\n * Client-side OpenTelemetry Instrumentation\n * \n * Initializes OTEL in the browser to send component traces to the collector\n */\n\nimport { WebTracerProvider } from \"@opentelemetry/sdk-trace-web\"\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport { ZoneContextManager } from \"@opentelemetry/context-zone\"\nimport { Resource } from \"@opentelemetry/resources\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\n\nlet isInitialized = false\n\nexport interface TracingConfig {\n serviceName: string\n apiEndpoint?: string // Default: /api/traces\n}\n\nexport function initializeClientTracing(config: TracingConfig) {\n // Only initialize once\n if (isInitialized || typeof window === \"undefined\") {\n return\n }\n\n console.log(\"🔍 [Client Tracing] Initializing...\")\n\n try {\n // Build absolute URL for the API endpoint\n const apiEndpoint = config.apiEndpoint || \"/api/traces\"\n const absoluteUrl = typeof window !== \"undefined\" \n ? `${window.location.origin}${apiEndpoint}`\n : apiEndpoint\n\n // Configure OTLP exporter to use Next.js API proxy (avoids CORS)\n const exporter = new OTLPTraceExporter({\n url: absoluteUrl, // Must be absolute URL\n })\n\n // Create batch processor\n const batchProcessor = new BatchSpanProcessor(exporter)\n\n // Create tracer provider with service name\n const provider = new WebTracerProvider({\n resource: new Resource({\n [ATTR_SERVICE_NAME]: config.serviceName,\n }),\n spanProcessors: [batchProcessor],\n })\n\n // Register the provider\n provider.register({\n contextManager: new ZoneContextManager(),\n })\n\n isInitialized = true\n console.log(\"✅ [Client Tracing] Initialized successfully\")\n console.log(`📍 Service: ${config.serviceName}`)\n console.log(`📍 Endpoint: ${absoluteUrl}`)\n } catch (error) {\n console.error(\"❌ [Client Tracing] Failed to initialize:\", error)\n }\n}\n","\"use client\"\n\n/**\n * TracingProvider Component\n * \n * Initializes OpenTelemetry tracing on the client side\n * Wrap your app with this provider to enable tracing\n */\n\nimport { useEffect, type ReactNode } from \"react\"\nimport { initializeClientTracing, type TracingConfig } from \"./client-instrumentation\"\n\ninterface TracingProviderProps {\n children?: ReactNode\n config: TracingConfig\n}\n\nexport function TracingProvider({ children, config }: TracingProviderProps) {\n useEffect(() => {\n initializeClientTracing(config)\n }, [config])\n\n return <>{children}</>\n}\n","\"use client\"\n\n/**\n * React Hooks for Component Tracing\n * \n * Provides easy-to-use hooks for tracing component interactions\n */\n\nimport { useCallback, useEffect } from \"react\"\nimport { ComponentTracer } from \"./tracer\"\nimport { ComponentStatus } from \"./types\"\nimport type { InteractionType, ComponentStatusCode } from \"./types\"\n\n/**\n * Hook for tracing component interactions\n */\nexport function useComponentTrace(componentName: string) {\n // Record component mount\n useEffect(() => {\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"mount\")\n }\n\n return () => {\n // Record component unmount\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"unmount\")\n }\n }\n }, [componentName])\n\n // Click tracking\n const recordClick = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"click\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Change tracking\n const recordChange = useCallback(\n (\n value: unknown,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"change\",\n {\n \"component.value\": typeof value === \"string\" ? value : String(value),\n ...metadata,\n },\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Focus tracking\n const recordFocus = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"focus\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Blur tracking\n const recordBlur = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"blur\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Custom interaction tracking\n const recordCustom = useCallback(\n (\n interaction: InteractionType,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n interaction,\n metadata || {},\n statusCode\n )\n },\n [componentName]\n )\n\n return {\n recordClick,\n recordChange,\n recordFocus,\n recordBlur,\n recordCustom,\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/session.ts","../src/tracer.ts","../src/client-instrumentation.ts","../src/provider.tsx","../src/hooks.ts"],"names":["tracer","useEffect"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * OpenTelemetry Tracing Types\n * \n * Type definitions for component tracing and telemetry\n */\n\n// Interaction types for component events\nexport type InteractionType =\n | \"click\"\n | \"change\"\n | \"focus\"\n | \"blur\"\n | \"submit\"\n | \"open\"\n | \"close\"\n | \"select\"\n | \"search\"\n | \"render\"\n | \"mount\"\n | \"unmount\"\n | \"error\"\n | \"custom\"\n\n// Component status codes (aligned with HTTP status codes)\nexport const ComponentStatus = {\n OK: 200,\n ERROR: 500,\n VALIDATION_ERROR: 400,\n NOT_FOUND: 404,\n} as const\n\nexport type ComponentStatusCode =\n (typeof ComponentStatus)[keyof typeof ComponentStatus]\n\n// Trace attributes for components\nexport interface ComponentTraceAttributes {\n \"component.name\": string\n \"component.type\": string\n \"component.interaction\": InteractionType\n \"component.status\": ComponentStatusCode\n \"component.props\"?: Record<string, unknown>\n \"component.error\"?: string\n \"component.duration_ms\"?: number\n \"user.action\"?: string\n [key: string]: unknown\n}\n\n// Trace event for components\nexport interface ComponentTraceEvent {\n name: string\n timestamp: number\n attributes: ComponentTraceAttributes\n status: ComponentStatusCode\n}\n\n// Configuration for traced components\nexport interface TraceConfig {\n enabled: boolean\n sampleRate: number // 0.0 to 1.0\n captureProps: boolean\n captureErrors: boolean\n destinations: (\"otlp\" | \"console\" | \"custom\")[]\n}\n","/**\n * Session Management for Tracing\n * \n * Manages user session IDs with 30-minute timeout\n */\n\nconst SESSION_KEY = \"tracing_session_id\"\nconst SESSION_TIMEOUT = 30 * 60 * 1000 // 30 minutes in milliseconds\n\ninterface SessionData {\n id: string\n lastActivity: number\n}\n\nexport class SessionManager {\n /**\n * Get or create a session ID\n */\n static getSessionId(): string {\n if (typeof window === \"undefined\") {\n return \"server-side\"\n }\n\n try {\n const storedData = localStorage.getItem(SESSION_KEY)\n\n if (storedData) {\n const sessionData: SessionData = JSON.parse(storedData)\n const now = Date.now()\n\n // Check if session has expired\n if (now - sessionData.lastActivity < SESSION_TIMEOUT) {\n // Update last activity\n sessionData.lastActivity = now\n localStorage.setItem(SESSION_KEY, JSON.stringify(sessionData))\n return sessionData.id\n }\n }\n\n // Create new session\n const newSessionId = this.generateSessionId()\n const newSessionData: SessionData = {\n id: newSessionId,\n lastActivity: Date.now(),\n }\n localStorage.setItem(SESSION_KEY, JSON.stringify(newSessionData))\n return newSessionId\n } catch (error) {\n // Fallback if localStorage is not available\n console.warn(\"Failed to access localStorage for session management:\", error)\n return this.generateSessionId()\n }\n }\n\n /**\n * Generate a unique session ID\n */\n private static generateSessionId(): string {\n return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`\n }\n\n /**\n * Clear the current session\n */\n static clearSession(): void {\n if (typeof window !== \"undefined\") {\n try {\n localStorage.removeItem(SESSION_KEY)\n } catch (error) {\n console.warn(\"Failed to clear session:\", error)\n }\n }\n }\n}\n","/**\n * Component Tracer\n * \n * Core tracing functionality for UI components using OpenTelemetry\n */\n\nimport type {\n ComponentStatusCode,\n ComponentTraceAttributes,\n InteractionType,\n} from \"./types\"\nimport { ComponentStatus } from \"./types\"\nimport { SessionManager } from \"./session\"\n\n// Lazy-load OpenTelemetry to avoid bundle bloat\nlet tracer: any = null\n\nasync function getTracer() {\n if (tracer) return tracer\n\n if (typeof window === \"undefined\") {\n // Server-side: return a no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n\n try {\n // Dynamically import OpenTelemetry (only in browser)\n const { trace } = await import(\"@opentelemetry/api\")\n tracer = trace.getTracer(\"component-tracer\")\n return tracer\n } catch (error) {\n console.warn(\"OpenTelemetry not available, tracing disabled:\", error)\n // Return no-op tracer\n return {\n startSpan: () => ({\n setAttributes: () => {},\n setStatus: () => {},\n end: () => {},\n }),\n }\n }\n}\n\nexport class ComponentTracer {\n /**\n * Record a component interaction\n */\n static async recordInteraction(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {},\n statusCode: ComponentStatusCode = ComponentStatus.OK\n ): Promise<void> {\n const tracer = await getTracer()\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1, // INTERNAL\n startTime: Date.now(),\n })\n\n // Auto-capture current page from URL\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n\n // Get session ID\n const sessionId = SessionManager.getSessionId()\n\n // Set component attributes\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.status\": statusCode,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: (attributes[\"page\"] as string) || currentPage,\n \"session.id\": sessionId,\n })\n\n // Add all additional attributes\n Object.entries(attributes).forEach(([key, value]) => {\n // Skip already set attributes and complex objects\n if (\n key === \"component.name\" ||\n key === \"component.interaction\" ||\n key === \"component.status\" ||\n key === \"component.type\" ||\n key === \"page\" ||\n key === \"session.id\"\n ) {\n return\n }\n\n // Only add primitive values (string, number, boolean)\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set status\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2, // OK = 1, ERROR = 2\n })\n\n // End span\n span.end()\n }\n\n /**\n * Start a long-running operation (e.g., form submission)\n * Returns an operation ID that can be used to end the operation\n */\n static async startOperation(\n componentName: string,\n interaction: InteractionType,\n attributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<string> {\n const tracer = await getTracer()\n const operationId = `${componentName}_${interaction}_${Date.now()}`\n const span = tracer.startSpan(`${componentName}.${interaction}`, {\n kind: 1,\n startTime: Date.now(),\n })\n\n // Store span for later retrieval\n if (typeof window !== \"undefined\") {\n ;(window as any).__activeSpans = (window as any).__activeSpans || {}\n ;(window as any).__activeSpans[operationId] = span\n }\n\n // Set initial attributes\n const currentPage =\n typeof window !== \"undefined\" ? window.location.pathname : \"/\"\n const sessionId = SessionManager.getSessionId()\n\n span.setAttributes({\n \"component.name\": componentName,\n \"component.interaction\": interaction,\n \"component.type\": (attributes[\"component.type\"] as string) || \"component\",\n page: currentPage,\n \"session.id\": sessionId,\n ...attributes,\n })\n\n return operationId\n }\n\n /**\n * End a long-running operation\n */\n static async endOperation(\n operationId: string,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n additionalAttributes: Partial<ComponentTraceAttributes> = {}\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const span = (window as any).__activeSpans?.[operationId]\n if (!span) {\n console.warn(`No active span found for operation: ${operationId}`)\n return\n }\n\n // Add final attributes\n Object.entries(additionalAttributes).forEach(([key, value]) => {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n span.setAttribute(key, value)\n }\n })\n\n // Set final status\n span.setAttribute(\"component.status\", statusCode)\n span.setStatus({\n code: statusCode === ComponentStatus.OK ? 1 : 2,\n })\n\n span.end()\n\n // Clean up\n delete (window as any).__activeSpans[operationId]\n }\n\n /**\n * Capture a custom error manually\n * @param error - The error object or message\n * @param context - Additional context about the error\n */\n static async captureError(\n error: Error | string,\n context?: {\n componentName?: string;\n userId?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(\"error.captured\", {\n attributes: {\n \"component.type\": \"error\",\n \"interaction.type\": \"error\",\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add error details\n const errorMessage = error instanceof Error ? error.message : error\n const errorStack = error instanceof Error ? error.stack : undefined\n\n span.setAttribute(\"error\", true)\n span.setAttribute(\"error.message\", errorMessage)\n if (errorStack) {\n span.setAttribute(\"error.stack\", errorStack)\n }\n\n // Add context\n if (context?.componentName) {\n span.setAttribute(\"component.name\", context.componentName)\n }\n if (context?.userId) {\n span.setAttribute(\"user.id\", context.userId)\n }\n if (context?.metadata) {\n Object.entries(context.metadata).forEach(([key, value]) => {\n span.setAttribute(`error.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set error status\n span.setAttribute(\"component.status\", ComponentStatus.ERROR)\n span.setStatus({\n code: 2, // SpanStatusCode.ERROR\n message: errorMessage,\n })\n\n span.end()\n\n console.log(`[ComponentTracer] Captured error: ${errorMessage}`)\n }\n\n /**\n * Track a custom business event\n * @param eventName - Name of the event (e.g., 'purchase_completed', 'user_signup')\n * @param properties - Event properties/metadata\n */\n static async trackEvent(\n eventName: string,\n properties?: {\n componentName?: string;\n userId?: string;\n value?: number;\n currency?: string;\n metadata?: Record<string, any>;\n }\n ): Promise<void> {\n if (typeof window === \"undefined\") return\n\n const { trace } = await import(\"@opentelemetry/api\")\n const tracer = trace.getTracer(\"component-tracer\")\n const span = tracer.startSpan(eventName, {\n attributes: {\n \"component.type\": \"custom-event\",\n \"interaction.type\": \"custom\",\n \"event.name\": eventName,\n \"session.id\": SessionManager.getSessionId(),\n },\n })\n\n // Add properties\n if (properties?.componentName) {\n span.setAttribute(\"component.name\", properties.componentName)\n }\n if (properties?.userId) {\n span.setAttribute(\"user.id\", properties.userId)\n }\n if (properties?.value !== undefined) {\n span.setAttribute(\"event.value\", properties.value)\n }\n if (properties?.currency) {\n span.setAttribute(\"event.currency\", properties.currency)\n }\n if (properties?.metadata) {\n Object.entries(properties.metadata).forEach(([key, value]) => {\n span.setAttribute(`event.metadata.${key}`, JSON.stringify(value))\n })\n }\n\n // Set success status\n span.setAttribute(\"component.status\", ComponentStatus.OK)\n span.setStatus({ code: 1 }) // SpanStatusCode.OK\n\n span.end()\n\n console.log(`[ComponentTracer] Tracked event: ${eventName}`, properties)\n }\n}\n","\"use client\"\n\n/**\n * Client-side OpenTelemetry Instrumentation\n * \n * Initializes OTEL in the browser to send component traces to the collector\n */\n\nimport { WebTracerProvider } from \"@opentelemetry/sdk-trace-web\"\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport { ZoneContextManager } from \"@opentelemetry/context-zone\"\nimport { Resource } from \"@opentelemetry/resources\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\n\nlet isInitialized = false\n\nexport interface TracingConfig {\n serviceName: string\n apiEndpoint?: string // Default: /api/traces\n headers?: Record<string, string> // Custom headers (e.g., x-api-key)\n}\n\nexport function initializeClientTracing(config: TracingConfig) {\n // Only initialize once\n if (isInitialized || typeof window === \"undefined\") {\n return\n }\n\n console.log(\"🔍 [Client Tracing] Initializing...\")\n\n try {\n // Build absolute URL for the API endpoint\n const apiEndpoint = config.apiEndpoint || \"/api/traces\"\n \n // Check if it's already an absolute URL\n const isAbsoluteUrl = apiEndpoint.startsWith(\"http://\") || apiEndpoint.startsWith(\"https://\")\n const absoluteUrl = isAbsoluteUrl \n ? apiEndpoint\n : (typeof window !== \"undefined\" ? `${window.location.origin}${apiEndpoint}` : apiEndpoint)\n\n // Configure OTLP exporter with custom headers\n const exporter = new OTLPTraceExporter({\n url: absoluteUrl,\n headers: config.headers || {},\n })\n\n // Create batch processor\n const batchProcessor = new BatchSpanProcessor(exporter)\n\n // Create tracer provider with service name\n const provider = new WebTracerProvider({\n resource: new Resource({\n [ATTR_SERVICE_NAME]: config.serviceName,\n }),\n spanProcessors: [batchProcessor],\n })\n\n // Register the provider\n provider.register({\n contextManager: new ZoneContextManager(),\n })\n\n isInitialized = true\n console.log(\"✅ [Client Tracing] Initialized successfully\")\n console.log(`📍 Service: ${config.serviceName}`)\n console.log(`📍 Endpoint: ${absoluteUrl}`)\n } catch (error) {\n console.error(\"❌ [Client Tracing] Failed to initialize:\", error)\n }\n}\n","\"use client\"\n\n/**\n * TracingProvider Component\n * \n * Initializes OpenTelemetry tracing on the client side\n * Wrap your app with this provider to enable tracing\n */\n\nimport { useEffect, type ReactNode } from \"react\"\nimport { initializeClientTracing, type TracingConfig } from \"./client-instrumentation\"\n\ninterface TracingProviderProps {\n children?: ReactNode\n config: TracingConfig\n}\n\nexport function TracingProvider({ children, config }: TracingProviderProps) {\n useEffect(() => {\n initializeClientTracing(config)\n }, [config])\n\n return <>{children}</>\n}\n","\"use client\"\n\n/**\n * React Hooks for Component Tracing\n * \n * Provides easy-to-use hooks for tracing component interactions\n */\n\nimport { useCallback, useEffect } from \"react\"\nimport { ComponentTracer } from \"./tracer\"\nimport { ComponentStatus } from \"./types\"\nimport type { InteractionType, ComponentStatusCode } from \"./types\"\n\n/**\n * Hook for tracing component interactions\n */\nexport function useComponentTrace(componentName: string) {\n // Record component mount\n useEffect(() => {\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"mount\")\n }\n\n return () => {\n // Record component unmount\n if (componentName) {\n ComponentTracer.recordInteraction(componentName, \"unmount\")\n }\n }\n }, [componentName])\n\n // Click tracking\n const recordClick = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"click\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Change tracking\n const recordChange = useCallback(\n (\n value: unknown,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"change\",\n {\n \"component.value\": typeof value === \"string\" ? value : String(value),\n ...metadata,\n },\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Focus tracking\n const recordFocus = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"focus\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Blur tracking\n const recordBlur = useCallback(\n (metadata?: Record<string, string | number | boolean>) => {\n ComponentTracer.recordInteraction(\n componentName,\n \"blur\",\n metadata || {},\n ComponentStatus.OK\n )\n },\n [componentName]\n )\n\n // Custom interaction tracking\n const recordCustom = useCallback(\n (\n interaction: InteractionType,\n statusCode: ComponentStatusCode = ComponentStatus.OK,\n metadata?: Record<string, string | number | boolean>\n ) => {\n ComponentTracer.recordInteraction(\n componentName,\n interaction,\n metadata || {},\n statusCode\n )\n },\n [componentName]\n )\n\n return {\n recordClick,\n recordChange,\n recordFocus,\n recordBlur,\n recordCustom,\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@potipher/otel-react",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "OpenTelemetry instrumentation for React components",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",