Skip to content

Commit ee25575

Browse files
docs: add section for the spotlight sdk (#1227)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 8363843 commit ee25575

File tree

3 files changed

+239
-2
lines changed

3 files changed

+239
-2
lines changed

packages/spotlight/src/server/sdk.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ const decompressors: Record<"gzip" | "deflate" | "br", (buf: Buffer) => Buffer>
1010

1111
export type ContentEncoding = keyof typeof decompressors;
1212

13-
export function createSpotlightBuffer() {
14-
return new MessageBuffer<EventContainer>();
13+
export function createSpotlightBuffer(size?: number) {
14+
return new MessageBuffer<EventContainer>(size);
1515
}
1616

1717
type PushToSpotlightBufferOptions = {

packages/website/astro.config.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ export default defineConfig({
107107
directory: "docs/sidecar",
108108
},
109109
},
110+
{
111+
label: "SDK",
112+
autogenerate: {
113+
directory: "docs/sdk",
114+
},
115+
},
110116
{
111117
label: "Contribute",
112118
autogenerate: {
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
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

Comments
 (0)