@logtide/sdk-node 0.6.0 → 0.7.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/README.md CHANGED
@@ -1,493 +1,493 @@
1
- <p align="center">
2
- <img src="https://raw.githubusercontent.com/logtide-dev/logtide/main/docs/images/logo.png" alt="LogTide Logo" width="400">
3
- </p>
4
-
5
- <h1 align="center">LogTide Node.js SDK</h1>
6
-
7
- <p align="center">
8
- <a href="https://www.npmjs.com/package/@logtide/sdk-node"><img src="https://img.shields.io/npm/v/@logtide/sdk-node?color=blue" alt="npm"></a>
9
- <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"></a>
10
- <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-20+-green.svg" alt="Node.js"></a>
11
- <a href="https://github.com/logtide-dev/logtide-javascript/releases"><img src="https://img.shields.io/github/v/release/logtide-dev/logtide-javascript" alt="Release"></a>
12
- </p>
13
-
14
- <p align="center">
15
- Official Node.js SDK for <a href="https://logtide.dev">LogTide</a> with automatic batching, retry logic, circuit breaker, query API, live streaming, and middleware support.
16
- </p>
17
-
18
- ---
19
-
20
- ## Features
21
-
22
- - **Automatic batching** with configurable size and interval
23
- - **Retry logic** with exponential backoff
24
- - **Circuit breaker** pattern for fault tolerance
25
- - **Max buffer size** with drop policy to prevent memory leaks
26
- - **Query API** for searching and filtering logs
27
- - **Live tail** with Server-Sent Events (SSE)
28
- - **Trace ID context** for distributed tracing
29
- - **Global metadata** added to all logs
30
- - **Structured error serialization**
31
- - **Internal metrics** (logs sent, errors, latency, etc.)
32
- - **Express & Fastify middleware** for auto-logging HTTP requests
33
- - **Full TypeScript support** with strict types
34
-
35
- ## Installation
36
-
37
- ```bash
38
- npm install @logtide/sdk-node
39
- # or
40
- pnpm add @logtide/sdk-node
41
- # or
42
- yarn add @logtide/sdk-node
43
- ```
44
-
45
- ## Quick Start
46
-
47
- ```typescript
48
- import { LogTideClient } from '@logtide/sdk-node';
49
-
50
- const client = new LogTideClient({
51
- apiUrl: 'http://localhost:8080',
52
- apiKey: 'lp_your_api_key_here',
53
- });
54
-
55
- // Send logs
56
- client.info('api-gateway', 'Server started', { port: 3000 });
57
- client.error('database', 'Connection failed', new Error('Timeout'));
58
-
59
- // Graceful shutdown
60
- process.on('SIGINT', async () => {
61
- await client.close();
62
- process.exit(0);
63
- });
64
- ```
65
-
66
- ---
67
-
68
- ## Configuration Options
69
-
70
- ### Basic Options
71
-
72
- | Option | Type | Default | Description |
73
- |--------|------|---------|-------------|
74
- | `apiUrl` | `string` | **required** | Base URL of your LogTide instance |
75
- | `apiKey` | `string` | **required** | Project API key (starts with `lp_`) |
76
- | `batchSize` | `number` | `100` | Number of logs to batch before sending |
77
- | `flushInterval` | `number` | `5000` | Interval in ms to auto-flush logs |
78
-
79
- ### Advanced Options
80
-
81
- | Option | Type | Default | Description |
82
- |--------|------|---------|-------------|
83
- | `maxBufferSize` | `number` | `10000` | Max logs in buffer (prevents memory leak) |
84
- | `maxRetries` | `number` | `3` | Max retry attempts on failure |
85
- | `retryDelayMs` | `number` | `1000` | Initial retry delay (exponential backoff) |
86
- | `circuitBreakerThreshold` | `number` | `5` | Failures before opening circuit |
87
- | `circuitBreakerResetMs` | `number` | `30000` | Time before retrying after circuit opens |
88
- | `enableMetrics` | `boolean` | `true` | Track internal metrics |
89
- | `debug` | `boolean` | `false` | Enable debug logging to console |
90
- | `globalMetadata` | `object` | `{}` | Metadata added to all logs |
91
- | `autoTraceId` | `boolean` | `false` | Auto-generate trace IDs for logs |
92
-
93
- ### Example: Full Configuration
94
-
95
- ```typescript
96
- const client = new LogTideClient({
97
- apiUrl: 'http://localhost:8080',
98
- apiKey: 'lp_your_api_key_here',
99
-
100
- // Batching
101
- batchSize: 100,
102
- flushInterval: 5000,
103
-
104
- // Buffer management
105
- maxBufferSize: 10000,
106
-
107
- // Retry with exponential backoff (1s -> 2s -> 4s)
108
- maxRetries: 3,
109
- retryDelayMs: 1000,
110
-
111
- // Circuit breaker
112
- circuitBreakerThreshold: 5,
113
- circuitBreakerResetMs: 30000,
114
-
115
- // Metrics & debugging
116
- enableMetrics: true,
117
- debug: true,
118
-
119
- // Global context
120
- globalMetadata: {
121
- env: process.env.NODE_ENV,
122
- version: '1.0.0',
123
- hostname: process.env.HOSTNAME,
124
- },
125
-
126
- // Auto trace IDs
127
- autoTraceId: false,
128
- });
129
- ```
130
-
131
- ---
132
-
133
- ## Logging Methods
134
-
135
- ### Basic Logging
136
-
137
- ```typescript
138
- client.debug('service-name', 'Debug message');
139
- client.info('service-name', 'Info message', { userId: 123 });
140
- client.warn('service-name', 'Warning message');
141
- client.error('service-name', 'Error message', { custom: 'data' });
142
- client.critical('service-name', 'Critical message');
143
- ```
144
-
145
- ### Error Logging with Auto-Serialization
146
-
147
- The SDK automatically serializes `Error` objects:
148
-
149
- ```typescript
150
- try {
151
- throw new Error('Database timeout');
152
- } catch (error) {
153
- // Automatically serializes error with stack trace
154
- client.error('database', 'Query failed', error);
155
- }
156
- ```
157
-
158
- Generated log metadata:
159
- ```json
160
- {
161
- "error": {
162
- "name": "Error",
163
- "message": "Database timeout",
164
- "stack": "Error: Database timeout\n at ..."
165
- }
166
- }
167
- ```
168
-
169
- ### Custom Log Entry
170
-
171
- ```typescript
172
- client.log({
173
- service: 'custom-service',
174
- level: 'info',
175
- message: 'Custom log',
176
- time: new Date().toISOString(),
177
- metadata: { key: 'value' },
178
- trace_id: 'custom-trace-id',
179
- });
180
- ```
181
-
182
- ---
183
-
184
- ## Trace ID Context
185
-
186
- Track requests across services with trace IDs.
187
-
188
- ### Manual Trace ID
189
-
190
- ```typescript
191
- client.setTraceId('request-123');
192
-
193
- client.info('api', 'Request received');
194
- client.info('database', 'Querying users');
195
- client.info('api', 'Response sent');
196
-
197
- client.setTraceId(null); // Clear context
198
- ```
199
-
200
- ### Scoped Trace ID
201
-
202
- ```typescript
203
- client.withTraceId('request-456', () => {
204
- client.info('api', 'Processing in context');
205
- client.warn('cache', 'Cache miss');
206
- });
207
- // Trace ID automatically restored after block
208
- ```
209
-
210
- ### Auto-Generated Trace ID
211
-
212
- ```typescript
213
- client.withNewTraceId(() => {
214
- client.info('worker', 'Background job started');
215
- client.info('worker', 'Job completed');
216
- });
217
- ```
218
-
219
- ---
220
-
221
- ## Query API
222
-
223
- Search and retrieve logs programmatically.
224
-
225
- ### Basic Query
226
-
227
- ```typescript
228
- const result = await client.query({
229
- service: 'api-gateway',
230
- level: 'error',
231
- from: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24h
232
- to: new Date(),
233
- limit: 100,
234
- offset: 0,
235
- });
236
-
237
- console.log(`Found ${result.total} logs`);
238
- console.log(result.logs);
239
- ```
240
-
241
- ### Full-Text Search
242
-
243
- ```typescript
244
- const result = await client.query({
245
- q: 'timeout',
246
- limit: 50,
247
- });
248
- ```
249
-
250
- ### Get Logs by Trace ID
251
-
252
- ```typescript
253
- const logs = await client.getByTraceId('trace-123');
254
- console.log(`Trace has ${logs.length} logs`);
255
- ```
256
-
257
- ### Aggregated Statistics
258
-
259
- ```typescript
260
- const stats = await client.getAggregatedStats({
261
- from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
262
- to: new Date(),
263
- interval: '1h', // '1m' | '5m' | '1h' | '1d'
264
- service: 'api-gateway', // Optional
265
- });
266
-
267
- console.log(stats.timeseries); // Time-bucketed counts
268
- console.log(stats.top_services); // Top services by log count
269
- console.log(stats.top_errors); // Most common errors
270
- ```
271
-
272
- ---
273
-
274
- ## Live Tail (Streaming)
275
-
276
- Stream logs in real-time using Server-Sent Events.
277
-
278
- ```typescript
279
- const cleanup = client.stream({
280
- service: 'api-gateway', // Optional filter
281
- level: 'error', // Optional filter
282
-
283
- onLog: (log) => {
284
- console.log(`[${log.time}] ${log.level}: ${log.message}`);
285
- },
286
-
287
- onError: (error) => {
288
- console.error('Stream error:', error);
289
- },
290
- });
291
-
292
- // Stop streaming when done
293
- setTimeout(() => {
294
- cleanup();
295
- }, 60000);
296
- ```
297
-
298
- ---
299
-
300
- ## Metrics
301
-
302
- Track SDK performance and health.
303
-
304
- ```typescript
305
- const metrics = client.getMetrics();
306
-
307
- console.log(metrics.logsSent); // Total logs sent
308
- console.log(metrics.logsDropped); // Logs dropped (buffer full)
309
- console.log(metrics.errors); // Send errors
310
- console.log(metrics.retries); // Retry attempts
311
- console.log(metrics.avgLatencyMs); // Average send latency
312
- console.log(metrics.circuitBreakerTrips); // Circuit breaker openings
313
-
314
- // Get circuit breaker state
315
- console.log(client.getCircuitBreakerState()); // 'CLOSED' | 'OPEN' | 'HALF_OPEN'
316
-
317
- // Reset metrics
318
- client.resetMetrics();
319
- ```
320
-
321
- ---
322
-
323
- ## Middleware Integration
324
-
325
- LogTide provides ready-to-use middleware for popular frameworks.
326
-
327
- ### Express Middleware
328
-
329
- Auto-log all HTTP requests and responses.
330
-
331
- ```typescript
332
- import express from 'express';
333
- import { LogTideClient, logTideMiddleware } from '@logtide/sdk-node';
334
-
335
- const app = express();
336
- const logger = new LogTideClient({
337
- apiUrl: 'http://localhost:8080',
338
- apiKey: 'lp_your_api_key_here',
339
- });
340
-
341
- app.use(
342
- logTideMiddleware({
343
- client: logger,
344
- serviceName: 'express-api',
345
- logRequests: true,
346
- logResponses: true,
347
- logErrors: true,
348
- includeHeaders: false,
349
- includeBody: false,
350
- skipHealthCheck: true,
351
- skipPaths: ['/metrics'],
352
- }),
353
- );
354
-
355
- app.get('/', (req, res) => {
356
- res.json({ message: 'Hello' });
357
- });
358
-
359
- app.listen(3000);
360
- ```
361
-
362
- **Logged automatically:**
363
- - Request: `GET /users/123`
364
- - Response: `GET /users/123 200 (45ms)`
365
- - Errors: `Request error: Internal Server Error`
366
-
367
- ### Fastify Plugin
368
-
369
- ```typescript
370
- import Fastify from 'fastify';
371
- import { LogTideClient, logTideFastifyPlugin } from '@logtide/sdk-node';
372
-
373
- const fastify = Fastify();
374
- const logger = new LogTideClient({
375
- apiUrl: 'http://localhost:8080',
376
- apiKey: 'lp_your_api_key_here',
377
- });
378
-
379
- await fastify.register(logTideFastifyPlugin, {
380
- client: logger,
381
- serviceName: 'fastify-api',
382
- logRequests: true,
383
- logResponses: true,
384
- logErrors: true,
385
- skipHealthCheck: true,
386
- });
387
-
388
- fastify.get('/', async () => ({ message: 'Hello' }));
389
-
390
- await fastify.listen({ port: 3000 });
391
- ```
392
-
393
- ---
394
-
395
- ## Examples
396
-
397
- See the [examples/](./examples) directory for complete working examples:
398
-
399
- - **[basic.ts](./examples/basic.ts)** - Simple usage
400
- - **[advanced.ts](./examples/advanced.ts)** - All advanced features
401
- - **[express-middleware.ts](./examples/express-middleware.ts)** - Express integration
402
- - **[fastify-plugin.ts](./examples/fastify-plugin.ts)** - Fastify integration
403
-
404
- ---
405
-
406
- ## Best Practices
407
-
408
- ### 1. Always Close on Shutdown
409
-
410
- ```typescript
411
- process.on('SIGINT', async () => {
412
- await client.close(); // Flushes buffered logs
413
- process.exit(0);
414
- });
415
-
416
- process.on('SIGTERM', async () => {
417
- await client.close();
418
- process.exit(0);
419
- });
420
- ```
421
-
422
- ### 2. Use Global Metadata
423
-
424
- ```typescript
425
- const client = new LogTideClient({
426
- apiUrl: 'http://localhost:8080',
427
- apiKey: 'lp_your_api_key_here',
428
- globalMetadata: {
429
- env: process.env.NODE_ENV,
430
- version: require('./package.json').version,
431
- region: process.env.AWS_REGION,
432
- pod: process.env.HOSTNAME,
433
- },
434
- });
435
- ```
436
-
437
- ### 3. Enable Debug Mode in Development
438
-
439
- ```typescript
440
- const client = new LogTideClient({
441
- apiUrl: 'http://localhost:8080',
442
- apiKey: 'lp_your_api_key_here',
443
- debug: process.env.NODE_ENV === 'development',
444
- });
445
- ```
446
-
447
- ### 4. Monitor Metrics in Production
448
-
449
- ```typescript
450
- setInterval(() => {
451
- const metrics = client.getMetrics();
452
-
453
- if (metrics.logsDropped > 0) {
454
- console.warn(`Logs dropped: ${metrics.logsDropped}`);
455
- }
456
-
457
- if (metrics.circuitBreakerTrips > 0) {
458
- console.error('Circuit breaker is OPEN!');
459
- }
460
- }, 60000);
461
- ```
462
-
463
- ---
464
-
465
- ## TypeScript Support
466
-
467
- Fully typed with strict TypeScript support:
468
-
469
- ```typescript
470
- import type {
471
- LogTideClient,
472
- LogEntry,
473
- QueryOptions,
474
- LogsResponse,
475
- ClientMetrics,
476
- } from '@logtide/sdk-node';
477
- ```
478
-
479
- ---
480
-
481
- ## Contributing
482
-
483
- Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
484
-
485
- ## License
486
-
487
- MIT License - see [LICENSE](LICENSE) for details.
488
-
489
- ## Links
490
-
491
- - [LogTide Website](https://logtide.dev)
492
- - [Documentation](https://logtide.dev/docs/sdks/node/)
493
- - [GitHub Issues](https://github.com/logtide-dev/logtide-javascript/issues)
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/logtide-dev/logtide/main/docs/images/logo.png" alt="LogTide Logo" width="400">
3
+ </p>
4
+
5
+ <h1 align="center">LogTide Node.js SDK</h1>
6
+
7
+ <p align="center">
8
+ <a href="https://www.npmjs.com/package/@logtide/sdk-node"><img src="https://img.shields.io/npm/v/@logtide/sdk-node?color=blue" alt="npm"></a>
9
+ <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License"></a>
10
+ <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-20+-green.svg" alt="Node.js"></a>
11
+ <a href="https://github.com/logtide-dev/logtide-javascript/releases"><img src="https://img.shields.io/github/v/release/logtide-dev/logtide-javascript" alt="Release"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ Official Node.js SDK for <a href="https://logtide.dev">LogTide</a> with automatic batching, retry logic, circuit breaker, query API, live streaming, and middleware support.
16
+ </p>
17
+
18
+ ---
19
+
20
+ ## Features
21
+
22
+ - **Automatic batching** with configurable size and interval
23
+ - **Retry logic** with exponential backoff
24
+ - **Circuit breaker** pattern for fault tolerance
25
+ - **Max buffer size** with drop policy to prevent memory leaks
26
+ - **Query API** for searching and filtering logs
27
+ - **Live tail** with Server-Sent Events (SSE)
28
+ - **Trace ID context** for distributed tracing
29
+ - **Global metadata** added to all logs
30
+ - **Structured error serialization**
31
+ - **Internal metrics** (logs sent, errors, latency, etc.)
32
+ - **Express & Fastify middleware** for auto-logging HTTP requests
33
+ - **Full TypeScript support** with strict types
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ npm install @logtide/sdk-node
39
+ # or
40
+ pnpm add @logtide/sdk-node
41
+ # or
42
+ yarn add @logtide/sdk-node
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```typescript
48
+ import { LogTideClient } from '@logtide/sdk-node';
49
+
50
+ const client = new LogTideClient({
51
+ apiUrl: 'http://localhost:8080',
52
+ apiKey: 'lp_your_api_key_here',
53
+ });
54
+
55
+ // Send logs
56
+ client.info('api-gateway', 'Server started', { port: 3000 });
57
+ client.error('database', 'Connection failed', new Error('Timeout'));
58
+
59
+ // Graceful shutdown
60
+ process.on('SIGINT', async () => {
61
+ await client.close();
62
+ process.exit(0);
63
+ });
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Configuration Options
69
+
70
+ ### Basic Options
71
+
72
+ | Option | Type | Default | Description |
73
+ |--------|------|---------|-------------|
74
+ | `apiUrl` | `string` | **required** | Base URL of your LogTide instance |
75
+ | `apiKey` | `string` | **required** | Project API key (starts with `lp_`) |
76
+ | `batchSize` | `number` | `100` | Number of logs to batch before sending |
77
+ | `flushInterval` | `number` | `5000` | Interval in ms to auto-flush logs |
78
+
79
+ ### Advanced Options
80
+
81
+ | Option | Type | Default | Description |
82
+ |--------|------|---------|-------------|
83
+ | `maxBufferSize` | `number` | `10000` | Max logs in buffer (prevents memory leak) |
84
+ | `maxRetries` | `number` | `3` | Max retry attempts on failure |
85
+ | `retryDelayMs` | `number` | `1000` | Initial retry delay (exponential backoff) |
86
+ | `circuitBreakerThreshold` | `number` | `5` | Failures before opening circuit |
87
+ | `circuitBreakerResetMs` | `number` | `30000` | Time before retrying after circuit opens |
88
+ | `enableMetrics` | `boolean` | `true` | Track internal metrics |
89
+ | `debug` | `boolean` | `false` | Enable debug logging to console |
90
+ | `globalMetadata` | `object` | `{}` | Metadata added to all logs |
91
+ | `autoTraceId` | `boolean` | `false` | Auto-generate trace IDs for logs |
92
+
93
+ ### Example: Full Configuration
94
+
95
+ ```typescript
96
+ const client = new LogTideClient({
97
+ apiUrl: 'http://localhost:8080',
98
+ apiKey: 'lp_your_api_key_here',
99
+
100
+ // Batching
101
+ batchSize: 100,
102
+ flushInterval: 5000,
103
+
104
+ // Buffer management
105
+ maxBufferSize: 10000,
106
+
107
+ // Retry with exponential backoff (1s -> 2s -> 4s)
108
+ maxRetries: 3,
109
+ retryDelayMs: 1000,
110
+
111
+ // Circuit breaker
112
+ circuitBreakerThreshold: 5,
113
+ circuitBreakerResetMs: 30000,
114
+
115
+ // Metrics & debugging
116
+ enableMetrics: true,
117
+ debug: true,
118
+
119
+ // Global context
120
+ globalMetadata: {
121
+ env: process.env.NODE_ENV,
122
+ version: '1.0.0',
123
+ hostname: process.env.HOSTNAME,
124
+ },
125
+
126
+ // Auto trace IDs
127
+ autoTraceId: false,
128
+ });
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Logging Methods
134
+
135
+ ### Basic Logging
136
+
137
+ ```typescript
138
+ client.debug('service-name', 'Debug message');
139
+ client.info('service-name', 'Info message', { userId: 123 });
140
+ client.warn('service-name', 'Warning message');
141
+ client.error('service-name', 'Error message', { custom: 'data' });
142
+ client.critical('service-name', 'Critical message');
143
+ ```
144
+
145
+ ### Error Logging with Auto-Serialization
146
+
147
+ The SDK automatically serializes `Error` objects:
148
+
149
+ ```typescript
150
+ try {
151
+ throw new Error('Database timeout');
152
+ } catch (error) {
153
+ // Automatically serializes error with stack trace
154
+ client.error('database', 'Query failed', error);
155
+ }
156
+ ```
157
+
158
+ Generated log metadata:
159
+ ```json
160
+ {
161
+ "error": {
162
+ "name": "Error",
163
+ "message": "Database timeout",
164
+ "stack": "Error: Database timeout\n at ..."
165
+ }
166
+ }
167
+ ```
168
+
169
+ ### Custom Log Entry
170
+
171
+ ```typescript
172
+ client.log({
173
+ service: 'custom-service',
174
+ level: 'info',
175
+ message: 'Custom log',
176
+ time: new Date().toISOString(),
177
+ metadata: { key: 'value' },
178
+ trace_id: 'custom-trace-id',
179
+ });
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Trace ID Context
185
+
186
+ Track requests across services with trace IDs.
187
+
188
+ ### Manual Trace ID
189
+
190
+ ```typescript
191
+ client.setTraceId('request-123');
192
+
193
+ client.info('api', 'Request received');
194
+ client.info('database', 'Querying users');
195
+ client.info('api', 'Response sent');
196
+
197
+ client.setTraceId(null); // Clear context
198
+ ```
199
+
200
+ ### Scoped Trace ID
201
+
202
+ ```typescript
203
+ client.withTraceId('request-456', () => {
204
+ client.info('api', 'Processing in context');
205
+ client.warn('cache', 'Cache miss');
206
+ });
207
+ // Trace ID automatically restored after block
208
+ ```
209
+
210
+ ### Auto-Generated Trace ID
211
+
212
+ ```typescript
213
+ client.withNewTraceId(() => {
214
+ client.info('worker', 'Background job started');
215
+ client.info('worker', 'Job completed');
216
+ });
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Query API
222
+
223
+ Search and retrieve logs programmatically.
224
+
225
+ ### Basic Query
226
+
227
+ ```typescript
228
+ const result = await client.query({
229
+ service: 'api-gateway',
230
+ level: 'error',
231
+ from: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24h
232
+ to: new Date(),
233
+ limit: 100,
234
+ offset: 0,
235
+ });
236
+
237
+ console.log(`Found ${result.total} logs`);
238
+ console.log(result.logs);
239
+ ```
240
+
241
+ ### Full-Text Search
242
+
243
+ ```typescript
244
+ const result = await client.query({
245
+ q: 'timeout',
246
+ limit: 50,
247
+ });
248
+ ```
249
+
250
+ ### Get Logs by Trace ID
251
+
252
+ ```typescript
253
+ const logs = await client.getByTraceId('trace-123');
254
+ console.log(`Trace has ${logs.length} logs`);
255
+ ```
256
+
257
+ ### Aggregated Statistics
258
+
259
+ ```typescript
260
+ const stats = await client.getAggregatedStats({
261
+ from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
262
+ to: new Date(),
263
+ interval: '1h', // '1m' | '5m' | '1h' | '1d'
264
+ service: 'api-gateway', // Optional
265
+ });
266
+
267
+ console.log(stats.timeseries); // Time-bucketed counts
268
+ console.log(stats.top_services); // Top services by log count
269
+ console.log(stats.top_errors); // Most common errors
270
+ ```
271
+
272
+ ---
273
+
274
+ ## Live Tail (Streaming)
275
+
276
+ Stream logs in real-time using Server-Sent Events.
277
+
278
+ ```typescript
279
+ const cleanup = client.stream({
280
+ service: 'api-gateway', // Optional filter
281
+ level: 'error', // Optional filter
282
+
283
+ onLog: (log) => {
284
+ console.log(`[${log.time}] ${log.level}: ${log.message}`);
285
+ },
286
+
287
+ onError: (error) => {
288
+ console.error('Stream error:', error);
289
+ },
290
+ });
291
+
292
+ // Stop streaming when done
293
+ setTimeout(() => {
294
+ cleanup();
295
+ }, 60000);
296
+ ```
297
+
298
+ ---
299
+
300
+ ## Metrics
301
+
302
+ Track SDK performance and health.
303
+
304
+ ```typescript
305
+ const metrics = client.getMetrics();
306
+
307
+ console.log(metrics.logsSent); // Total logs sent
308
+ console.log(metrics.logsDropped); // Logs dropped (buffer full)
309
+ console.log(metrics.errors); // Send errors
310
+ console.log(metrics.retries); // Retry attempts
311
+ console.log(metrics.avgLatencyMs); // Average send latency
312
+ console.log(metrics.circuitBreakerTrips); // Circuit breaker openings
313
+
314
+ // Get circuit breaker state
315
+ console.log(client.getCircuitBreakerState()); // 'CLOSED' | 'OPEN' | 'HALF_OPEN'
316
+
317
+ // Reset metrics
318
+ client.resetMetrics();
319
+ ```
320
+
321
+ ---
322
+
323
+ ## Middleware Integration
324
+
325
+ LogTide provides ready-to-use middleware for popular frameworks.
326
+
327
+ ### Express Middleware
328
+
329
+ Auto-log all HTTP requests and responses.
330
+
331
+ ```typescript
332
+ import express from 'express';
333
+ import { LogTideClient, logTideMiddleware } from '@logtide/sdk-node';
334
+
335
+ const app = express();
336
+ const logger = new LogTideClient({
337
+ apiUrl: 'http://localhost:8080',
338
+ apiKey: 'lp_your_api_key_here',
339
+ });
340
+
341
+ app.use(
342
+ logTideMiddleware({
343
+ client: logger,
344
+ serviceName: 'express-api',
345
+ logRequests: true,
346
+ logResponses: true,
347
+ logErrors: true,
348
+ includeHeaders: false,
349
+ includeBody: false,
350
+ skipHealthCheck: true,
351
+ skipPaths: ['/metrics'],
352
+ }),
353
+ );
354
+
355
+ app.get('/', (req, res) => {
356
+ res.json({ message: 'Hello' });
357
+ });
358
+
359
+ app.listen(3000);
360
+ ```
361
+
362
+ **Logged automatically:**
363
+ - Request: `GET /users/123`
364
+ - Response: `GET /users/123 200 (45ms)`
365
+ - Errors: `Request error: Internal Server Error`
366
+
367
+ ### Fastify Plugin
368
+
369
+ ```typescript
370
+ import Fastify from 'fastify';
371
+ import { LogTideClient, logTideFastifyPlugin } from '@logtide/sdk-node';
372
+
373
+ const fastify = Fastify();
374
+ const logger = new LogTideClient({
375
+ apiUrl: 'http://localhost:8080',
376
+ apiKey: 'lp_your_api_key_here',
377
+ });
378
+
379
+ await fastify.register(logTideFastifyPlugin, {
380
+ client: logger,
381
+ serviceName: 'fastify-api',
382
+ logRequests: true,
383
+ logResponses: true,
384
+ logErrors: true,
385
+ skipHealthCheck: true,
386
+ });
387
+
388
+ fastify.get('/', async () => ({ message: 'Hello' }));
389
+
390
+ await fastify.listen({ port: 3000 });
391
+ ```
392
+
393
+ ---
394
+
395
+ ## Examples
396
+
397
+ See the [examples/](./examples) directory for complete working examples:
398
+
399
+ - **[basic.ts](./examples/basic.ts)** - Simple usage
400
+ - **[advanced.ts](./examples/advanced.ts)** - All advanced features
401
+ - **[express-middleware.ts](./examples/express-middleware.ts)** - Express integration
402
+ - **[fastify-plugin.ts](./examples/fastify-plugin.ts)** - Fastify integration
403
+
404
+ ---
405
+
406
+ ## Best Practices
407
+
408
+ ### 1. Always Close on Shutdown
409
+
410
+ ```typescript
411
+ process.on('SIGINT', async () => {
412
+ await client.close(); // Flushes buffered logs
413
+ process.exit(0);
414
+ });
415
+
416
+ process.on('SIGTERM', async () => {
417
+ await client.close();
418
+ process.exit(0);
419
+ });
420
+ ```
421
+
422
+ ### 2. Use Global Metadata
423
+
424
+ ```typescript
425
+ const client = new LogTideClient({
426
+ apiUrl: 'http://localhost:8080',
427
+ apiKey: 'lp_your_api_key_here',
428
+ globalMetadata: {
429
+ env: process.env.NODE_ENV,
430
+ version: require('./package.json').version,
431
+ region: process.env.AWS_REGION,
432
+ pod: process.env.HOSTNAME,
433
+ },
434
+ });
435
+ ```
436
+
437
+ ### 3. Enable Debug Mode in Development
438
+
439
+ ```typescript
440
+ const client = new LogTideClient({
441
+ apiUrl: 'http://localhost:8080',
442
+ apiKey: 'lp_your_api_key_here',
443
+ debug: process.env.NODE_ENV === 'development',
444
+ });
445
+ ```
446
+
447
+ ### 4. Monitor Metrics in Production
448
+
449
+ ```typescript
450
+ setInterval(() => {
451
+ const metrics = client.getMetrics();
452
+
453
+ if (metrics.logsDropped > 0) {
454
+ console.warn(`Logs dropped: ${metrics.logsDropped}`);
455
+ }
456
+
457
+ if (metrics.circuitBreakerTrips > 0) {
458
+ console.error('Circuit breaker is OPEN!');
459
+ }
460
+ }, 60000);
461
+ ```
462
+
463
+ ---
464
+
465
+ ## TypeScript Support
466
+
467
+ Fully typed with strict TypeScript support:
468
+
469
+ ```typescript
470
+ import type {
471
+ LogTideClient,
472
+ LogEntry,
473
+ QueryOptions,
474
+ LogsResponse,
475
+ ClientMetrics,
476
+ } from '@logtide/sdk-node';
477
+ ```
478
+
479
+ ---
480
+
481
+ ## Contributing
482
+
483
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
484
+
485
+ ## License
486
+
487
+ MIT License - see [LICENSE](LICENSE) for details.
488
+
489
+ ## Links
490
+
491
+ - [LogTide Website](https://logtide.dev)
492
+ - [Documentation](https://logtide.dev/docs/sdks/node/)
493
+ - [GitHub Issues](https://github.com/logtide-dev/logtide-javascript/issues)