0
# Platform Support
1
2
OpenTelemetry SDK Trace Base provides platform-specific implementations optimized for browser and Node.js environments. These implementations offer better performance and platform-appropriate behavior for ID generation and batch processing.
3
4
## Capabilities
5
6
### Core IdGenerator Interface
7
8
Platform-specific ID generators implement the base IdGenerator interface for creating trace and span identifiers.
9
10
```typescript { .api }
11
/**
12
* Interface for generating trace and span IDs
13
*/
14
interface IdGenerator {
15
/**
16
* Generate a random trace ID
17
* @returns 32-character lowercase hexadecimal string representing a 16-byte trace ID
18
*/
19
generateTraceId(): string;
20
21
/**
22
* Generate a random span ID
23
* @returns 16-character lowercase hexadecimal string representing an 8-byte span ID
24
*/
25
generateSpanId(): string;
26
}
27
```
28
29
**ID Format Requirements:**
30
- Trace IDs: 32 characters, lowercase hexadecimal, represents 16 bytes (128 bits)
31
- Span IDs: 16 characters, lowercase hexadecimal, represents 8 bytes (64 bits)
32
- All IDs must be non-zero
33
- IDs should be cryptographically random for security and distribution
34
35
### Browser Platform
36
37
Browser-specific implementations optimized for web environments with appropriate fallbacks for limited APIs.
38
39
#### Browser RandomIdGenerator
40
41
```typescript { .api }
42
/**
43
* Browser implementation of ID generator using Math.random()
44
*/
45
class RandomIdGenerator implements IdGenerator {
46
/**
47
* Generate trace ID using browser-safe random number generation
48
* @returns 32-character hex trace ID
49
*/
50
generateTraceId(): string;
51
52
/**
53
* Generate span ID using browser-safe random number generation
54
* @returns 16-character hex span ID
55
*/
56
generateSpanId(): string;
57
}
58
```
59
60
**Browser Implementation Details:**
61
- Uses `Math.random()` for random number generation
62
- Fallback-safe for all browser environments
63
- Ensures non-zero IDs by regenerating if all bytes are zero
64
- No external dependencies or Node.js-specific APIs
65
66
**Usage Examples:**
67
68
```typescript
69
import { BasicTracerProvider, RandomIdGenerator } from '@opentelemetry/sdk-trace-base';
70
71
// Browser-specific tracer provider
72
const provider = new BasicTracerProvider({
73
idGenerator: new RandomIdGenerator(),
74
resource: new Resource({
75
'service.name': 'web-app',
76
'deployment.environment': 'browser'
77
})
78
});
79
80
// ID generator works in all browser contexts
81
const generator = new RandomIdGenerator();
82
const traceId = generator.generateTraceId(); // e.g., "a1b2c3d4e5f6789012345678901234567890abcd"
83
const spanId = generator.generateSpanId(); // e.g., "1234567890abcdef"
84
```
85
86
#### Browser BatchSpanProcessor
87
88
```typescript { .api }
89
/**
90
* Browser-specific batch span processor with page lifecycle integration
91
*/
92
class BatchSpanProcessor implements SpanProcessor {
93
/**
94
* @param exporter - The span exporter to send batched spans to
95
* @param config - Browser-specific configuration options
96
*/
97
constructor(exporter: SpanExporter, config?: BatchSpanProcessorBrowserConfig);
98
99
/**
100
* Forces flush of all pending spans within the configured timeout
101
* @returns Promise that resolves when flush completes
102
*/
103
forceFlush(): Promise<void>;
104
105
/**
106
* No-op: does nothing when span starts
107
*/
108
onStart(span: Span, parentContext: Context): void;
109
110
/**
111
* Adds span to buffer for batched export if sampled
112
* @param span - The span to add to the batch
113
*/
114
onEnd(span: ReadableSpan): void;
115
116
/**
117
* Shuts down the processor and flushes remaining spans
118
* @returns Promise that resolves when shutdown completes
119
*/
120
shutdown(): Promise<void>;
121
}
122
123
/**
124
* Browser-specific batch processor configuration
125
*/
126
interface BatchSpanProcessorBrowserConfig extends BufferConfig {
127
/**
128
* Disable flush when user navigates away or closes tab
129
* Auto flush is enabled by default for better data collection
130
*/
131
disableAutoFlushOnDocumentHide?: boolean;
132
}
133
```
134
135
**Browser-Specific Features:**
136
- **Page Lifecycle Integration**: Listens for `visibilitychange` events
137
- **Safari Compatibility**: Uses `pagehide` event as Safari fallback
138
- **Auto-Flush on Navigation**: Automatically flushes spans when page becomes hidden
139
- **Mobile Support**: Handles app switching on mobile devices
140
141
**Event Handling:**
142
1. `visibilitychange` event → flushes spans when `document.hidden` becomes `true`
143
2. `pagehide` event → Safari-specific fallback for page unload
144
3. Graceful degradation if events are not supported
145
146
**Usage Examples:**
147
148
```typescript
149
import { BasicTracerProvider, BatchSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
150
151
// Browser batch processor with auto-flush (default behavior)
152
const provider = new BasicTracerProvider({
153
spanProcessors: [
154
new BatchSpanProcessor(new ConsoleSpanExporter())
155
]
156
});
157
158
// Disable auto-flush for single-page applications
159
const provider = new BasicTracerProvider({
160
spanProcessors: [
161
new BatchSpanProcessor(new ConsoleSpanExporter(), {
162
disableAutoFlushOnDocumentHide: true,
163
maxExportBatchSize: 100,
164
scheduledDelayMillis: 3000
165
})
166
]
167
});
168
169
// Mobile-optimized configuration
170
const provider = new BasicTracerProvider({
171
spanProcessors: [
172
new BatchSpanProcessor(new ConsoleSpanExporter(), {
173
maxExportBatchSize: 50, // Smaller batches for mobile
174
scheduledDelayMillis: 2000, // More frequent exports
175
maxQueueSize: 500 // Smaller memory footprint
176
})
177
]
178
});
179
```
180
181
### Node.js Platform
182
183
Node.js-specific implementations optimized for server environments with better performance characteristics.
184
185
#### Node.js RandomIdGenerator
186
187
```typescript { .api }
188
/**
189
* Node.js implementation using Buffer for improved performance
190
*/
191
class RandomIdGenerator implements IdGenerator {
192
/**
193
* Generate trace ID using Node.js Buffer for better performance
194
* @returns 32-character hex trace ID
195
*/
196
generateTraceId(): string;
197
198
/**
199
* Generate span ID using Node.js Buffer for better performance
200
* @returns 16-character hex span ID
201
*/
202
generateSpanId(): string;
203
}
204
```
205
206
**Node.js Implementation Details:**
207
- Uses `Buffer.allocUnsafe()` for better performance
208
- Uses `writeUInt32BE()` for efficient random number writing
209
- Ensures non-zero IDs by setting last byte to 1 if all zeros detected
210
- Optimized for high-throughput server environments
211
212
**Performance Benefits:**
213
- ~2-3x faster than browser implementation
214
- Lower memory allocation overhead
215
- Better entropy distribution
216
- Suitable for high-frequency ID generation
217
218
**Usage Examples:**
219
220
```typescript
221
import { BasicTracerProvider, RandomIdGenerator } from '@opentelemetry/sdk-trace-base';
222
223
// Node.js-optimized tracer provider
224
const provider = new BasicTracerProvider({
225
idGenerator: new RandomIdGenerator(),
226
resource: new Resource({
227
'service.name': 'api-server',
228
'deployment.environment': 'production'
229
})
230
});
231
232
// High-performance ID generation for server use
233
const generator = new RandomIdGenerator();
234
235
// Generate many IDs efficiently
236
const traceIds = Array.from({ length: 1000 }, () => generator.generateTraceId());
237
const spanIds = Array.from({ length: 1000 }, () => generator.generateSpanId());
238
```
239
240
#### Node.js BatchSpanProcessor
241
242
```typescript { .api }
243
/**
244
* Node.js batch span processor implementation
245
*/
246
class BatchSpanProcessor implements SpanProcessor {
247
/**
248
* @param exporter - The span exporter to send batched spans to
249
* @param config - Standard buffer configuration
250
*/
251
constructor(exporter: SpanExporter, config?: BufferConfig);
252
253
/**
254
* Forces flush of all pending spans within the configured timeout
255
* @returns Promise that resolves when flush completes
256
*/
257
forceFlush(): Promise<void>;
258
259
/**
260
* No-op: does nothing when span starts
261
*/
262
onStart(span: Span, parentContext: Context): void;
263
264
/**
265
* Adds span to buffer for batched export if sampled
266
* @param span - The span to add to the batch
267
*/
268
onEnd(span: ReadableSpan): void;
269
270
/**
271
* Shuts down the processor and flushes remaining spans
272
* @returns Promise that resolves when shutdown completes
273
*/
274
shutdown(): Promise<void>;
275
}
276
```
277
278
**Node.js-Specific Features:**
279
- **No Page Lifecycle**: No browser-specific event listeners
280
- **Process Integration**: Works with Node.js process lifecycle events
281
- **High Throughput**: Optimized for server-side span volumes
282
- **Memory Management**: Better handling of large span queues
283
284
**Usage Examples:**
285
286
```typescript
287
import { BasicTracerProvider, BatchSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
288
289
// Server-optimized batch processor
290
const provider = new BasicTracerProvider({
291
spanProcessors: [
292
// Example with external exporter (requires @opentelemetry/exporter-jaeger)
293
// new BatchSpanProcessor(new JaegerExporter(), {
294
// maxExportBatchSize: 1000, // Larger batches for servers
295
// scheduledDelayMillis: 5000, // Less frequent exports
296
// maxQueueSize: 4096, // Larger queue for high throughput
297
// exportTimeoutMillis: 30000 // Longer timeout for network exports
298
// })
299
new BatchSpanProcessor(new ConsoleSpanExporter(), {
300
maxExportBatchSize: 1000, // Larger batches for servers
301
scheduledDelayMillis: 5000, // Less frequent exports
302
maxQueueSize: 4096, // Larger queue for high throughput
303
exportTimeoutMillis: 30000 // Longer timeout for network exports
304
})
305
]
306
});
307
308
// Process lifecycle integration
309
process.on('SIGTERM', async () => {
310
console.log('Received SIGTERM, shutting down gracefully');
311
await provider.forceFlush();
312
await provider.shutdown();
313
process.exit(0);
314
});
315
316
process.on('SIGINT', async () => {
317
console.log('Received SIGINT, shutting down gracefully');
318
await provider.forceFlush();
319
await provider.shutdown();
320
process.exit(0);
321
});
322
```
323
324
### Platform Import Pattern
325
326
The package automatically selects the appropriate platform implementation based on the environment.
327
328
```typescript { .api }
329
// Platform exports are automatically selected
330
export { BatchSpanProcessor, RandomIdGenerator } from './platform';
331
332
// Platform-specific implementations are in:
333
// - ./platform/browser/index.ts (for browser)
334
// - ./platform/node/index.ts (for Node.js)
335
```
336
337
**Automatic Platform Detection:**
338
- Browser environments get browser-optimized implementations
339
- Node.js environments get Node.js-optimized implementations
340
- Build tools handle platform-specific bundling
341
- No manual platform selection required
342
343
**Usage Examples:**
344
345
```typescript
346
// Imports automatically resolve to correct platform
347
import { BasicTracerProvider, BatchSpanProcessor, RandomIdGenerator } from '@opentelemetry/sdk-trace-base';
348
349
// Same code works in both browser and Node.js
350
const provider = new BasicTracerProvider({
351
idGenerator: new RandomIdGenerator(), // Platform-appropriate implementation
352
spanProcessors: [
353
new BatchSpanProcessor(new ConsoleSpanExporter()) // Platform-appropriate implementation
354
]
355
});
356
```
357
358
### Custom Platform Implementations
359
360
You can create custom platform-specific implementations by extending base classes or implementing interfaces.
361
362
**Usage Examples:**
363
364
```typescript
365
import { IdGenerator } from '@opentelemetry/sdk-trace-base';
366
import { webcrypto } from 'crypto';
367
368
// Custom secure ID generator using Web Crypto API
369
class SecureIdGenerator implements IdGenerator {
370
generateTraceId(): string {
371
const bytes = new Uint8Array(16);
372
webcrypto.getRandomValues(bytes);
373
374
// Ensure non-zero
375
if (bytes.every(b => b === 0)) {
376
bytes[15] = 1;
377
}
378
379
return Array.from(bytes)
380
.map(b => b.toString(16).padStart(2, '0'))
381
.join('');
382
}
383
384
generateSpanId(): string {
385
const bytes = new Uint8Array(8);
386
webcrypto.getRandomValues(bytes);
387
388
// Ensure non-zero
389
if (bytes.every(b => b === 0)) {
390
bytes[7] = 1;
391
}
392
393
return Array.from(bytes)
394
.map(b => b.toString(16).padStart(2, '0'))
395
.join('');
396
}
397
}
398
399
// Custom batch processor with platform-specific optimizations
400
class OptimizedBatchSpanProcessor implements SpanProcessor {
401
private batchProcessor: BatchSpanProcessor;
402
403
constructor(exporter: SpanExporter, config?: BufferConfig) {
404
// Platform-specific defaults
405
const platformConfig = {
406
maxExportBatchSize: typeof window !== 'undefined' ? 100 : 1000,
407
scheduledDelayMillis: typeof window !== 'undefined' ? 2000 : 5000,
408
...config
409
};
410
411
this.batchProcessor = new BatchSpanProcessor(exporter, platformConfig);
412
}
413
414
forceFlush(): Promise<void> {
415
return this.batchProcessor.forceFlush();
416
}
417
418
onStart(span: Span, parentContext: Context): void {
419
this.batchProcessor.onStart(span, parentContext);
420
}
421
422
onEnd(span: ReadableSpan): void {
423
this.batchProcessor.onEnd(span);
424
}
425
426
shutdown(): Promise<void> {
427
if (typeof window !== 'undefined') {
428
console.log('Browser shutdown');
429
} else {
430
console.log('Node.js shutdown');
431
}
432
return this.batchProcessor.shutdown();
433
}
434
}
435
436
// Use custom implementations
437
const provider = new BasicTracerProvider({
438
idGenerator: new SecureIdGenerator(),
439
spanProcessors: [
440
new OptimizedBatchSpanProcessor(new ConsoleSpanExporter())
441
]
442
});
443
```
444
445
### Environment Compatibility
446
447
The platform implementations handle various environment constraints and limitations.
448
449
**Browser Compatibility:**
450
- Works in all modern browsers (ES2017+)
451
- Progressive enhancement for newer APIs
452
- Graceful fallbacks for limited environments
453
- Web Worker support
454
- Service Worker support
455
456
**Node.js Compatibility:**
457
- Node.js 14+ for optimal performance
458
- Uses native Node.js APIs for best performance
459
- Works with serverless environments
460
- Compatible with clustering and worker threads
461
462
**Usage Examples:**
463
464
```typescript
465
// Universal setup that works everywhere
466
function createTracerProvider(environment: 'browser' | 'node' | 'worker') {
467
const baseConfig = {
468
resource: new Resource({
469
'service.name': 'universal-app',
470
'deployment.environment': environment
471
})
472
};
473
474
switch (environment) {
475
case 'browser':
476
return new BasicTracerProvider({
477
...baseConfig,
478
spanProcessors: [
479
new BatchSpanProcessor(new ConsoleSpanExporter(), {
480
maxExportBatchSize: 50,
481
scheduledDelayMillis: 2000
482
})
483
]
484
});
485
486
case 'node':
487
return new BasicTracerProvider({
488
...baseConfig,
489
spanProcessors: [
490
// Example with external exporter (requires @opentelemetry/exporter-jaeger)
491
// new BatchSpanProcessor(new JaegerExporter(), {
492
// maxExportBatchSize: 1000,
493
// scheduledDelayMillis: 5000
494
// })
495
new BatchSpanProcessor(new ConsoleSpanExporter(), {
496
maxExportBatchSize: 1000,
497
scheduledDelayMillis: 5000
498
})
499
]
500
});
501
502
case 'worker':
503
return new BasicTracerProvider({
504
...baseConfig,
505
spanProcessors: [
506
new SimpleSpanProcessor(new ConsoleSpanExporter())
507
]
508
});
509
}
510
}
511
512
// Auto-detect environment
513
const environment = typeof window !== 'undefined' ? 'browser' : 'node';
514
const provider = createTracerProvider(environment);
515
```