@cherrydotfun/collector-sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +497 -0
- package/dist/index.d.mts +225 -0
- package/dist/index.d.ts +225 -0
- package/dist/index.js +431 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +404 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Cherry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
# @cherrydotfun/collector-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for Cherry Collector — event tracking, logging, and metrics.
|
|
4
|
+
|
|
5
|
+
Collect errors, logs, and analytics events from your application and stream them to the Collector backend. Zero dependencies, works on browser, React Native, and Node.js.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @cherrydotfun/collector-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn add @cherrydotfun/collector-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun add @cherrydotfun/collector-sdk
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
Initialize the client, send events, and flush before exit:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { CollectorClient } from '@cherrydotfun/collector-sdk';
|
|
27
|
+
|
|
28
|
+
const collector = new CollectorClient({
|
|
29
|
+
baseUrl: 'https://collector.cherry.fun',
|
|
30
|
+
apiKey: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
|
|
31
|
+
platform: 'ios',
|
|
32
|
+
version: '2.1.0',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Initialize: fetch filter config and start refresh timer
|
|
36
|
+
await collector.init();
|
|
37
|
+
|
|
38
|
+
// Set context (attached to all subsequent events)
|
|
39
|
+
collector.setUser('wallet_address_or_user_id');
|
|
40
|
+
collector.setSession('session_uuid');
|
|
41
|
+
collector.setModule('messaging');
|
|
42
|
+
collector.setDevice('device_id');
|
|
43
|
+
|
|
44
|
+
// Send events
|
|
45
|
+
collector.error('WebSocket connection failed', { url: '/ws' });
|
|
46
|
+
collector.info('User logged in', { userId: 'wallet123' });
|
|
47
|
+
collector.debug('Cache hit', { key: 'messages_dm_123' });
|
|
48
|
+
collector.analytics('screen_view', 'ChatScreen', { fromScreen: 'RoomList' });
|
|
49
|
+
collector.analytics('button_click', 'Send message', { hasAttachment: true });
|
|
50
|
+
|
|
51
|
+
// Set metrics
|
|
52
|
+
await collector.metric('ws_connections', 42);
|
|
53
|
+
await collector.metricBatch([
|
|
54
|
+
{ key: 'ws_connections', value: 42 },
|
|
55
|
+
{ key: 'active_rooms', value: 15 },
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
// Flush remaining events and stop timers
|
|
59
|
+
await collector.flush();
|
|
60
|
+
collector.destroy();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Configuration
|
|
64
|
+
|
|
65
|
+
Pass a `CollectorConfig` object to the constructor:
|
|
66
|
+
|
|
67
|
+
| Option | Type | Default | Description |
|
|
68
|
+
|--------|------|---------|-------------|
|
|
69
|
+
| `baseUrl` | string | required | Base URL of the Collector backend (e.g. `https://collector.cherry.fun`). |
|
|
70
|
+
| `apiKey` | string | required | Project API key from the admin panel. |
|
|
71
|
+
| `platform` | string | undefined | Client platform (e.g. `ios`, `android`, `web`, `server`). Attached to all events. |
|
|
72
|
+
| `version` | string | undefined | Application version string (e.g. `2.1.0`). Attached to all events. |
|
|
73
|
+
| `batchSize` | number | 10 | Number of events per batch before auto-flush. |
|
|
74
|
+
| `flushIntervalMs` | number | 5000 | Milliseconds between automatic batch flushes. |
|
|
75
|
+
| `configRefreshSec` | number | 300 | Seconds between config refreshes from server. |
|
|
76
|
+
| `debug` | boolean | false | Enable debug logging to `console.debug`. |
|
|
77
|
+
| `onError` | function | undefined | Called when network or API errors occur. Receives `(error, context)`. |
|
|
78
|
+
|
|
79
|
+
## API Reference
|
|
80
|
+
|
|
81
|
+
### Lifecycle
|
|
82
|
+
|
|
83
|
+
#### `init(): Promise<void>`
|
|
84
|
+
|
|
85
|
+
Initialize the client. Fetches filter configuration from the server and starts the periodic config refresh timer. Must be called before sending events.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
await collector.init();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### `flush(): Promise<void>`
|
|
92
|
+
|
|
93
|
+
Flush all queued events to the server immediately. Returns when the send completes (or fails silently).
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
await collector.flush();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### `destroy(): void`
|
|
100
|
+
|
|
101
|
+
Stop all timers and flush remaining events. Call before application exit or when the client is no longer needed.
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
collector.destroy();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Context
|
|
108
|
+
|
|
109
|
+
These setters attach context to all subsequent events:
|
|
110
|
+
|
|
111
|
+
#### `setUser(userId: string): void`
|
|
112
|
+
|
|
113
|
+
Set the user ID.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
collector.setUser('wallet_address_or_user_id');
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### `setSession(sessionId: string): void`
|
|
120
|
+
|
|
121
|
+
Set the session ID.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
collector.setSession('session_uuid');
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### `setModule(module: string): void`
|
|
128
|
+
|
|
129
|
+
Set the default module name.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
collector.setModule('messaging');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### `setDevice(deviceId: string): void`
|
|
136
|
+
|
|
137
|
+
Set the device ID.
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
collector.setDevice('device_uuid_or_id');
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Errors
|
|
144
|
+
|
|
145
|
+
#### `error(message: string, params?: Record<string, unknown> & { stackTrace?: string }): void`
|
|
146
|
+
|
|
147
|
+
Send an error event. The special `stackTrace` key is extracted and sent as the structured `stackTrace.raw` field.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
try {
|
|
151
|
+
await fetchData();
|
|
152
|
+
} catch (e) {
|
|
153
|
+
collector.error('Failed to fetch data', {
|
|
154
|
+
url: '/api/data',
|
|
155
|
+
stackTrace: e instanceof Error ? e.stack : undefined,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Logging
|
|
161
|
+
|
|
162
|
+
#### `log(level: LogLevel, message: string, params?: Record<string, unknown>): void`
|
|
163
|
+
|
|
164
|
+
Send a log event with an explicit level (`fatal`, `error`, `warn`, `info`, or `debug`).
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
collector.log('warn', 'Slow query detected', { duration: 2500 });
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### `fatal(message: string, params?: Record<string, unknown>): void`
|
|
171
|
+
|
|
172
|
+
Shorthand for `log('fatal', message, params)`.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
collector.fatal('Critical system failure');
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### `error(message: string, params?: Record<string, unknown>): void`
|
|
179
|
+
|
|
180
|
+
Shorthand for `log('error', message, params)`. Note: this is different from the `error()` method above, which has special stackTrace handling.
|
|
181
|
+
|
|
182
|
+
#### `warn(message: string, params?: Record<string, unknown>): void`
|
|
183
|
+
|
|
184
|
+
Shorthand for `log('warn', message, params)`.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
collector.warn('High memory usage', { mb: 512 });
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### `info(message: string, params?: Record<string, unknown>): void`
|
|
191
|
+
|
|
192
|
+
Shorthand for `log('info', message, params)`.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
collector.info('Server started', { port: 3000 });
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### `debug(message: string, params?: Record<string, unknown>): void`
|
|
199
|
+
|
|
200
|
+
Shorthand for `log('debug', message, params)`.
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
collector.debug('Cache miss', { key: 'user_settings_123' });
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Analytics
|
|
207
|
+
|
|
208
|
+
#### `analytics(event: string, message: string, params?: Record<string, unknown>): void`
|
|
209
|
+
|
|
210
|
+
Send an analytics event. The `event` parameter is an event name (e.g. `screen_view`, `button_click`), and `message` is a human-readable description.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
collector.analytics('screen_view', 'ChatScreen', {
|
|
214
|
+
fromScreen: 'RoomList',
|
|
215
|
+
roomType: 'dm',
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
collector.analytics('button_click', 'Send message', {
|
|
219
|
+
hasAttachment: true,
|
|
220
|
+
messageLength: 42,
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Metrics
|
|
225
|
+
|
|
226
|
+
Metrics are sent immediately (not batched).
|
|
227
|
+
|
|
228
|
+
#### `metric(key: string, value: number): Promise<void>`
|
|
229
|
+
|
|
230
|
+
Set a single metric value.
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
await collector.metric('ws_connections', 42);
|
|
234
|
+
await collector.metric('active_rooms', 15);
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### `metricBatch(ops: MetricOp[]): Promise<void>`
|
|
238
|
+
|
|
239
|
+
Set multiple metric values in one request. The backend accepts up to 100 operations per call.
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
await collector.metricBatch([
|
|
243
|
+
{ key: 'ws_connections', value: 42 },
|
|
244
|
+
{ key: 'active_rooms', value: 15 },
|
|
245
|
+
{ key: 'cpu_usage', value: 34.5 },
|
|
246
|
+
]);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Direct Send
|
|
250
|
+
|
|
251
|
+
#### `send(event: Partial<CollectorEvent> & { type: CollectorEvent['type']; message: string }): Promise<void>`
|
|
252
|
+
|
|
253
|
+
Send a single event immediately via `POST /api/collect`, bypassing the batch queue. Useful for critical events that must not be delayed.
|
|
254
|
+
|
|
255
|
+
The event is enriched with context (userId, sessionId, platform, etc.) and filtered against disabled patterns, same as queued events.
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
await collector.send({
|
|
259
|
+
type: 'error',
|
|
260
|
+
level: 'error',
|
|
261
|
+
message: 'Critical error',
|
|
262
|
+
params: { severity: 'high' },
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Configuration
|
|
267
|
+
|
|
268
|
+
#### `getConfig(): ConfigResponse | null`
|
|
269
|
+
|
|
270
|
+
Returns the last successfully fetched server configuration, or `null` if no config has been loaded yet.
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
const config = collector.getConfig();
|
|
274
|
+
if (config) {
|
|
275
|
+
console.log('Disabled patterns:', config.disabled);
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### `refreshConfig(): Promise<void>`
|
|
280
|
+
|
|
281
|
+
Force-refresh the filter configuration from the server. Normally called automatically on the configured interval.
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
await collector.refreshConfig();
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Observability
|
|
288
|
+
|
|
289
|
+
#### `getStats(): CollectorStats`
|
|
290
|
+
|
|
291
|
+
Returns SDK telemetry counters: events sent, dropped (filtered), failed, and current queue size.
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
const stats = collector.getStats();
|
|
295
|
+
console.log(`Sent: ${stats.sent}, Dropped: ${stats.dropped}, Failed: ${stats.failed}`);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### `isInitialized: boolean`
|
|
299
|
+
|
|
300
|
+
Read-only getter. Whether `init()` has been called and completed successfully.
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
if (collector.isInitialized) {
|
|
304
|
+
console.log('Ready to send events');
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Error Handling
|
|
309
|
+
|
|
310
|
+
Pass an `onError` callback to handle network and API errors:
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
const collector = new CollectorClient({
|
|
314
|
+
baseUrl: 'https://collector.cherry.fun',
|
|
315
|
+
apiKey: 'xxxxx',
|
|
316
|
+
onError: (error, context) => {
|
|
317
|
+
console.error(`Collector error in ${context}:`, error.message);
|
|
318
|
+
// Log to your error tracking service, retry, etc.
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
await collector.init();
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
The `context` parameter indicates where the error occurred:
|
|
326
|
+
- `sendBatch` - batch event send
|
|
327
|
+
- `send` - direct event send
|
|
328
|
+
- `metric` - metric set
|
|
329
|
+
- `metricBatch` - batch metric set
|
|
330
|
+
- `refreshConfig` - config refresh from server
|
|
331
|
+
|
|
332
|
+
## Event Filtering
|
|
333
|
+
|
|
334
|
+
The SDK fetches a filter configuration from the server on init and periodically refreshes it. Events matching disabled patterns are dropped client-side and not sent.
|
|
335
|
+
|
|
336
|
+
Patterns are hierarchical:
|
|
337
|
+
- `log.debug` — disable debug-level log events
|
|
338
|
+
- `log.*` — disable all log events
|
|
339
|
+
- `log` — disable all log events (alternate syntax)
|
|
340
|
+
- `*` — disable all events
|
|
341
|
+
|
|
342
|
+
When you call `collector.debug(...)`, the SDK checks if `log.debug` is in the disabled set. If so, the event is dropped locally (not sent), and the dropped counter is incremented.
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
const stats = collector.getStats();
|
|
346
|
+
console.log(`Events dropped: ${stats.dropped}`);
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Platform Support
|
|
350
|
+
|
|
351
|
+
The SDK requires `globalThis.fetch` to be available:
|
|
352
|
+
|
|
353
|
+
- **Browser:** Native fetch, or polyfill
|
|
354
|
+
- **React Native:** Built-in fetch (works with `http://` and `https://`)
|
|
355
|
+
- **Node.js 18+:** Native fetch
|
|
356
|
+
|
|
357
|
+
For Node.js < 18, provide a fetch polyfill (e.g. `node-fetch`):
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
import fetch from 'node-fetch';
|
|
361
|
+
globalThis.fetch = fetch;
|
|
362
|
+
|
|
363
|
+
const collector = new CollectorClient({ /* ... */ });
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Types
|
|
367
|
+
|
|
368
|
+
All types are exported from `@cherrydotfun/collector-sdk`:
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
import {
|
|
372
|
+
CollectorClient,
|
|
373
|
+
CollectorConfig,
|
|
374
|
+
CollectorEvent,
|
|
375
|
+
CollectorStats,
|
|
376
|
+
ConfigResponse,
|
|
377
|
+
EventType,
|
|
378
|
+
LogLevel,
|
|
379
|
+
AnalyticsLevel,
|
|
380
|
+
MetricOp,
|
|
381
|
+
IngestResponse,
|
|
382
|
+
BatchIngestResponse,
|
|
383
|
+
} from '@cherrydotfun/collector-sdk';
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Type Reference
|
|
387
|
+
|
|
388
|
+
| Type | Description |
|
|
389
|
+
|------|-------------|
|
|
390
|
+
| `CollectorClient` | Main client class for sending events and metrics. |
|
|
391
|
+
| `CollectorConfig` | Configuration options for the client. |
|
|
392
|
+
| `CollectorEvent` | Event payload sent to the backend. |
|
|
393
|
+
| `CollectorStats` | SDK telemetry counters (sent, dropped, failed, queueSize). |
|
|
394
|
+
| `ConfigResponse` | Server response from `GET /api/config` with disabled patterns. |
|
|
395
|
+
| `EventType` | Union of `'error' \| 'log' \| 'analytics'`. |
|
|
396
|
+
| `LogLevel` | Union of `'fatal' \| 'error' \| 'warn' \| 'info' \| 'debug'`. |
|
|
397
|
+
| `AnalyticsLevel` | Union of well-known analytics events or any custom string. |
|
|
398
|
+
| `MetricOp` | Single metric key-value pair for batch operations. |
|
|
399
|
+
| `IngestResponse` | Response from single event send. |
|
|
400
|
+
| `BatchIngestResponse` | Response from batch event send. |
|
|
401
|
+
|
|
402
|
+
## React Native Example
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
import { useEffect } from 'react';
|
|
406
|
+
import { AppState } from 'react-native';
|
|
407
|
+
import { CollectorClient } from '@cherrydotfun/collector-sdk';
|
|
408
|
+
|
|
409
|
+
const collector = new CollectorClient({
|
|
410
|
+
baseUrl: 'https://collector.cherry.fun',
|
|
411
|
+
apiKey: 'xxxxx',
|
|
412
|
+
platform: 'android', // or 'ios'
|
|
413
|
+
version: '2.1.0',
|
|
414
|
+
debug: false,
|
|
415
|
+
onError: (error, context) => {
|
|
416
|
+
console.error(`Collector error [${context}]:`, error);
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
export function App() {
|
|
421
|
+
useEffect(() => {
|
|
422
|
+
const init = async () => {
|
|
423
|
+
await collector.init();
|
|
424
|
+
collector.setUser(userWallet);
|
|
425
|
+
collector.setSession(sessionId);
|
|
426
|
+
collector.setModule('chat');
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
init();
|
|
430
|
+
|
|
431
|
+
const subscription = AppState.addEventListener('change', (state) => {
|
|
432
|
+
if (state === 'background') {
|
|
433
|
+
collector.flush();
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
return () => {
|
|
438
|
+
subscription.remove();
|
|
439
|
+
collector.flush();
|
|
440
|
+
collector.destroy();
|
|
441
|
+
};
|
|
442
|
+
}, []);
|
|
443
|
+
|
|
444
|
+
return (
|
|
445
|
+
// Your app components
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Node.js Server Example
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
import { CollectorClient } from '@cherrydotfun/collector-sdk';
|
|
454
|
+
|
|
455
|
+
const collector = new CollectorClient({
|
|
456
|
+
baseUrl: 'https://collector.cherry.fun',
|
|
457
|
+
apiKey: 'xxxxx',
|
|
458
|
+
platform: 'server',
|
|
459
|
+
version: '1.0.0',
|
|
460
|
+
debug: process.env.DEBUG === 'true',
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
await collector.init();
|
|
464
|
+
|
|
465
|
+
// Log application startup
|
|
466
|
+
collector.info('Server started', { port: 3000, env: process.env.NODE_ENV });
|
|
467
|
+
|
|
468
|
+
// Track unhandled errors
|
|
469
|
+
process.on('uncaughtException', (error) => {
|
|
470
|
+
collector.error('Uncaught exception', {
|
|
471
|
+
name: error.name,
|
|
472
|
+
message: error.message,
|
|
473
|
+
stackTrace: error.stack,
|
|
474
|
+
});
|
|
475
|
+
collector.flush().finally(() => process.exit(1));
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// On graceful shutdown
|
|
479
|
+
process.on('SIGTERM', async () => {
|
|
480
|
+
console.log('Shutting down...');
|
|
481
|
+
await collector.flush();
|
|
482
|
+
collector.destroy();
|
|
483
|
+
process.exit(0);
|
|
484
|
+
});
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
## Build Distribution
|
|
488
|
+
|
|
489
|
+
The SDK is published in multiple formats:
|
|
490
|
+
|
|
491
|
+
- **CommonJS** — `dist/index.js` for Node.js
|
|
492
|
+
- **ES Modules** — `dist/index.mjs` for bundlers
|
|
493
|
+
- **TypeScript Declarations** — `dist/index.d.ts`
|
|
494
|
+
|
|
495
|
+
## License
|
|
496
|
+
|
|
497
|
+
MIT
|