|
| 1 | +--- |
| 2 | +title: SDK Integration |
| 3 | +description: Embed Spotlight's event buffering into your own HTTP server |
| 4 | +sidebar: |
| 5 | + order: 0 |
| 6 | +--- |
| 7 | + |
| 8 | +The Spotlight SDK provides a programmatic API for integrating Spotlight's event buffering capabilities directly into your own HTTP server. Instead of running a separate sidecar process, you can embed the event receiving and storage functionality into your existing application. |
| 9 | + |
| 10 | +## When to Use the SDK |
| 11 | + |
| 12 | +Use the SDK when you need to: |
| 13 | + |
| 14 | +- **Embed Spotlight into an existing server**: You already have a Node.js HTTP server and want to add Spotlight endpoints without running a separate process |
| 15 | +- **Middleware pipelines**: You need fine-grained control over how telemetry data flows through your server |
| 16 | +- **Serverless functions**: You want Spotlight functionality in environments where running a separate sidecar isn't practical |
| 17 | + |
| 18 | +## Installation |
| 19 | + |
| 20 | +The SDK is included in the main `@spotlightjs/spotlight` package: |
| 21 | + |
| 22 | +```bash |
| 23 | +pnpm add @spotlightjs/spotlight |
| 24 | +``` |
| 25 | + |
| 26 | +## API Reference |
| 27 | + |
| 28 | +### `createSpotlightBuffer(size?)` |
| 29 | + |
| 30 | +Creates a new message buffer to store incoming telemetry events. |
| 31 | + |
| 32 | +```typescript |
| 33 | +import { createSpotlightBuffer } from '@spotlightjs/spotlight/sdk'; |
| 34 | + |
| 35 | +const buffer = createSpotlightBuffer(); |
| 36 | +``` |
| 37 | + |
| 38 | +The buffer stores events in memory with a default capacity of 500 items. When full, oldest events are automatically evicted. |
| 39 | + |
| 40 | +You can override the default capacity by passing a custom `size` parameter: |
| 41 | + |
| 42 | +```typescript |
| 43 | +// Create a buffer with capacity for 1000 events |
| 44 | +const buffer = createSpotlightBuffer(1000); |
| 45 | +``` |
| 46 | + |
| 47 | +This is useful when you expect high event volumes or want to retain more history for debugging. |
| 48 | + |
| 49 | +### `pushToSpotlightBuffer(options)` |
| 50 | + |
| 51 | +Pushes a telemetry event into the buffer. This is typically called when receiving a POST request from a Sentry SDK. |
| 52 | + |
| 53 | +```typescript |
| 54 | +import { pushToSpotlightBuffer } from '@spotlightjs/spotlight/sdk'; |
| 55 | + |
| 56 | +const container = pushToSpotlightBuffer({ |
| 57 | + spotlightBuffer: buffer, |
| 58 | + body: requestBody, // Buffer containing the raw request body |
| 59 | + encoding: 'gzip', // Optional: 'gzip' | 'deflate' | 'br' |
| 60 | + contentType: 'application/x-sentry-envelope', |
| 61 | + userAgent: 'sentry.javascript.browser/8.0.0', |
| 62 | +}); |
| 63 | +``` |
| 64 | + |
| 65 | +**Parameters:** |
| 66 | + |
| 67 | +| Parameter | Type | Description | |
| 68 | +|-----------|------|-------------| |
| 69 | +| `spotlightBuffer` | `MessageBuffer` | The buffer created by `createSpotlightBuffer()` | |
| 70 | +| `body` | `Buffer` | Raw request body (will be decompressed if encoding is set) | |
| 71 | +| `encoding` | `'gzip' \| 'deflate' \| 'br'` | Optional compression encoding | |
| 72 | +| `contentType` | `string` | Content-Type header value | |
| 73 | +| `userAgent` | `string` | User-Agent header value (for SDK identification) | |
| 74 | + |
| 75 | +**Returns:** An `EventContainer` with the parsed envelope, or `undefined` if no content type was provided. |
| 76 | + |
| 77 | +### `decompressBody(body, encoding)` |
| 78 | + |
| 79 | +Utility function to decompress request bodies. Supports gzip, deflate, and Brotli compression. |
| 80 | + |
| 81 | +```typescript |
| 82 | +import { decompressBody } from '@spotlightjs/spotlight/sdk'; |
| 83 | + |
| 84 | +const decompressed = decompressBody(compressedBuffer, 'gzip'); |
| 85 | +``` |
| 86 | + |
| 87 | +## Hono.js Example |
| 88 | + |
| 89 | +Here's a complete example of integrating Spotlight into a [Hono](https://hono.dev) application: |
| 90 | + |
| 91 | +```typescript |
| 92 | +import { serve } from '@hono/node-server'; |
| 93 | +import { Hono } from 'hono'; |
| 94 | +import { cors } from 'hono/cors'; |
| 95 | +import { |
| 96 | + createSpotlightBuffer, |
| 97 | + pushToSpotlightBuffer, |
| 98 | + decompressBody, |
| 99 | +} from '@spotlightjs/spotlight/sdk'; |
| 100 | + |
| 101 | +// Create the buffer to store events |
| 102 | +const buffer = createSpotlightBuffer(); |
| 103 | + |
| 104 | +const app = new Hono(); |
| 105 | + |
| 106 | +// Enable CORS for browser SDKs |
| 107 | +app.use(cors()); |
| 108 | + |
| 109 | +// Endpoint to receive telemetry from Sentry SDKs |
| 110 | +app.post('/stream', async (c) => { |
| 111 | + // Get content type, normalizing for browser SDK CORS workaround |
| 112 | + let contentType = c.req.header('content-type')?.split(';')[0].toLowerCase(); |
| 113 | + |
| 114 | + // Browser SDK may send as text/plain to avoid CORS preflight |
| 115 | + if (c.req.query('sentry_client')?.startsWith('sentry.javascript.browser')) { |
| 116 | + contentType = 'application/x-sentry-envelope'; |
| 117 | + } |
| 118 | + |
| 119 | + // Push to the buffer |
| 120 | + const container = pushToSpotlightBuffer({ |
| 121 | + spotlightBuffer: buffer, |
| 122 | + body: Buffer.from(await c.req.arrayBuffer()), |
| 123 | + encoding: c.req.header('Content-Encoding'), |
| 124 | + contentType, |
| 125 | + userAgent: c.req.header('User-Agent'), |
| 126 | + }); |
| 127 | + |
| 128 | + if (container) { |
| 129 | + console.log('Received event:', container.getEventTypesString()); |
| 130 | + } |
| 131 | + |
| 132 | + return c.body(null, 200); |
| 133 | +}); |
| 134 | + |
| 135 | +// Subscribe to events for real-time processing |
| 136 | +buffer.subscribe((container) => { |
| 137 | + const envelope = container.getParsedEnvelope(); |
| 138 | + const types = container.getEventTypes(); |
| 139 | + console.log('New event received:', types); |
| 140 | + |
| 141 | + // Process the event as needed |
| 142 | + // envelope.envelope[0] contains the envelope header |
| 143 | + // envelope.envelope[1] contains the items (errors, transactions, etc.) |
| 144 | +}); |
| 145 | + |
| 146 | +serve({ fetch: app.fetch, port: 8969 }, (info) => { |
| 147 | + console.log(`Spotlight SDK server running on http://localhost:${info.port}`); |
| 148 | +}); |
| 149 | +``` |
| 150 | + |
| 151 | +## Understanding the Event Flow |
| 152 | + |
| 153 | +``` |
| 154 | +Your Application → Sentry SDK → Your Server (SDK) → Buffer → Subscribers |
| 155 | +``` |
| 156 | + |
| 157 | +1. **Your application** instruments code with a Sentry SDK |
| 158 | +2. **Sentry SDK** sends telemetry to your server's `/stream` endpoint |
| 159 | +3. **Your server** uses `pushToSpotlightBuffer()` to store the event |
| 160 | +4. **Buffer** notifies all subscribers in real-time |
| 161 | +5. **Subscribers** can process, forward, or display events |
| 162 | + |
| 163 | +## Working with the Buffer |
| 164 | + |
| 165 | +### Reading Events |
| 166 | + |
| 167 | +The buffer supports filtering when reading events: |
| 168 | + |
| 169 | +```typescript |
| 170 | +// Get events from the last 60 seconds |
| 171 | +const recentEvents = buffer.read({ timeWindow: 60 }); |
| 172 | + |
| 173 | +// Get events from a specific file (for errors with stack traces) |
| 174 | +const fileEvents = buffer.read({ filename: 'auth.ts' }); |
| 175 | + |
| 176 | +// Get a specific event by envelope ID |
| 177 | +const specificEvent = buffer.read({ envelopeId: 'abc123...' }); |
| 178 | +``` |
| 179 | + |
| 180 | +### Subscribing to Events |
| 181 | + |
| 182 | +Subscribe to receive events as they arrive: |
| 183 | + |
| 184 | +```typescript |
| 185 | +const subscriptionId = buffer.subscribe((container) => { |
| 186 | + // Called for each new event |
| 187 | + const envelope = container.getParsedEnvelope(); |
| 188 | + console.log('Event:', envelope); |
| 189 | +}); |
| 190 | + |
| 191 | +// Later, unsubscribe when done |
| 192 | +buffer.unsubscribe(subscriptionId); |
| 193 | +``` |
| 194 | + |
| 195 | +### Clearing the Buffer |
| 196 | + |
| 197 | +```typescript |
| 198 | +// Clear all events |
| 199 | +buffer.clear(); |
| 200 | + |
| 201 | +// Soft reset (keeps subscribers; they continue from the new head position) |
| 202 | +buffer.reset(); |
| 203 | +``` |
| 204 | + |
| 205 | +## EventContainer API |
| 206 | + |
| 207 | +Each event in the buffer is wrapped in an `EventContainer`: |
| 208 | + |
| 209 | +```typescript |
| 210 | +const container = pushToSpotlightBuffer({ ... }); |
| 211 | + |
| 212 | +// Get the content type |
| 213 | +container.getContentType(); // 'application/x-sentry-envelope' |
| 214 | + |
| 215 | +// Get the raw data buffer |
| 216 | +container.getData(); // Buffer |
| 217 | + |
| 218 | +// Get the parsed envelope (lazy parsing) |
| 219 | +container.getParsedEnvelope(); // { envelope: [header, items] } |
| 220 | + |
| 221 | +// Get event types for logging |
| 222 | +container.getEventTypes(); // ['error', 'transaction'] |
| 223 | +container.getEventTypesString(); // 'error+transaction' |
| 224 | +``` |
| 225 | + |
| 226 | +## Next Steps |
| 227 | + |
| 228 | +- [Sidecar Overview](/docs/sidecar/) - Learn about the standalone sidecar server |
| 229 | +- [CLI Commands](/docs/cli/) - Run Spotlight from the command line |
| 230 | +- [MCP Integration](/docs/mcp/) - Connect to AI assistants |
| 231 | + |
0 commit comments