npm package: @sidharthhhh/nodejs-sdk
Description: Observer SDK for Node.js applications
Author: Observer
Latest version: 1.0.1

# Observer Node.js SDK

The official TypeScript/JavaScript SDK for the Observer API observability platform. Lightweight, non-intrusive instrumentation for Node.js web applications.

## Features

- ✅ **TypeScript Support**: Full TypeScript definitions
- ✅ **Zero Performance Impact**: Async background processing
- ✅ **Fail-Open Design**: Never crashes your application
- ✅ **Framework Support**: Express, Fastify, NestJS
- ✅ **Auto Route Normalization**: `/users/123` → `/users/:id`
- ✅ **Buffering**: Drops old events instead of consuming memory
- ✅ **Easy Integration**: Simple middleware/plugin installation

## Installation

```bash
npm install @observer/nodejs-sdk
```

## Local Installation (Without Publishing)

If you are developing locally and want to use this SDK in another project on your machine, you don't need to publish it to npm.

**Option 1: Install from folder**
```bash
npm install /path/to/observr/agents/nodejs-sdk
```

**Option 2: Install from tarball**
First, build and pack the SDK:
```bash
cd agents/nodejs-sdk
npm install
npm run build
npm pack
# This creates a file like observer-nodejs-sdk-1.0.0.tgz
```

Then in your other project:
```bash
npm install /path/to/observr/agents/nodejs-sdk/observer-nodejs-sdk-1.0.0.tgz

```

## Quick Start

### Express

```typescript
import express from 'express';
import { ObserverClient, observerMiddleware } from '@observer/nodejs-sdk';

// Create Observer client
const observer = new ObserverClient({
  ingestUrl: 'http://localhost:8080',
  apiKey: 'your-api-key',
  serviceName: 'my-service',
  environment: 'production',
});

const app = express();

// Add Observer middleware
app.use(observerMiddleware(observer));

app.get('/users/:id', (req, res) => {
  res.json({ userId: req.params.id });
});

app.listen(3000);

// Graceful shutdown
process.on('SIGTERM', async () => {
  await observer.close();
});
```

### Fastify

```typescript
import Fastify from 'fastify';
import { ObserverClient, observerPlugin } from '@observer/nodejs-sdk';

const observer = new ObserverClient({
  ingestUrl: 'http://localhost:8080',
  apiKey: 'your-api-key',
  serviceName: 'my-service',
  environment: 'production',
});

const fastify = Fastify();

// Register Observer plugin
fastify.register(observerPlugin, { client: observer });

fastify.get('/users/:id', async (request, reply) => {
  return { userId: request.params.id };
});

await fastify.listen({ port: 3000 });
```

### NestJS

```typescript
import { NestFactory } from '@nestjs/core';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { ObserverClient, ObserverInterceptor } from '@observer/nodejs-sdk';

const observer = new ObserverClient({
  ingestUrl: 'http://localhost:8080',
  apiKey: 'your-api-key',
  serviceName: 'my-service',
  environment: 'production',
});

@Module({
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useValue: new ObserverInterceptor(observer),
    },
  ],
})
class AppModule {}

const app = await NestFactory.create(AppModule);
await app.listen(3000);
```

## Configuration

### Full Configuration Options

```typescript
const observer = new ObserverClient({
  // Required
  ingestUrl: 'http://localhost:8080',
  apiKey: 'your-api-key',
  serviceName: 'my-service',
  environment: 'production',

  // Optional
  bufferSize: 2000,              // Default: 1000
  flushIntervalMs: 2000,         // Default: 1000
  maxRetries: 5,                 // Default: 3
  timeoutMs: 10000,              // Default: 5000
  enabled: true,                 // Default: true
  onError: (error) => {
    console.error('Observer error:', error);
  },
});
```

## Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `ingestUrl` | string | required | URL of Observer ingestion service |
| `apiKey` | string | required | API key for authentication |
| `serviceName` | string | required | Name of your service |
| `environment` | string | required | Environment (production, staging, etc.) |
| `bufferSize` | number | 1000 | Max events to buffer before dropping |
| `flushIntervalMs` | number | 1000 | How often to send events (ms) |
| `maxRetries` | number | 3 | Max retry attempts for failed requests |
| `timeoutMs` | number | 5000 | HTTP request timeout (ms) |
| `enabled` | boolean | true | Enable/disable instrumentation |
| `onError` | function | undefined | Custom error handler |

## How It Works

### 1. Request Tracking

When a request comes in, the middleware:
- Records start time
- Executes your handler  
- Records end time and status code
- Normalizes the route path
- Sends event to Observer (async, non-blocking)

### 2. Route Normalization

Dynamic paths are automatically normalized:

```
/users/123          → /users/:id
/posts/abc-def-123  → /posts/:id
/items/550e8400-... → /items/:id (UUIDs)
```

### 3. Async Processing

Events are buffered in memory and flushed:
- Every 1 second (default)
- Or when buffer reaches 1000 events (default)

### 4. Fail-Open Design

If something goes wrong:
- Never throws errors in your handlers
- Drops metrics instead of consuming memory
- Continues accepting requests even if Observer is down

## Manual Tracking

Track custom events manually:

```typescript
observer.track('GET', '/custom/endpoint', 200, 45.2);

// With error information
observer.trackWithError('POST', '/users', 500, 152.3, 'DatabaseError');
```

## Examples

See the [`examples/`](examples/) directory for complete working examples:

- [`examples/express/`](examples/express/) - Express example
- [`examples/fastify/`](examples/fastify/) - Fastify example
- [`examples/nestjs/`](examples/nestjs/) - NestJS example

## TypeScript

This SDK is written in TypeScript and includes full type definitions:

```typescript
import { ObserverClient, ObserverConfig } from '@observer/nodejs-sdk';

const config: ObserverConfig = {
  ingestUrl: 'http://localhost:8080',
  apiKey: 'your-api-key',
  serviceName: 'my-service',
  environment: 'production',
};

const observer = new ObserverClient(config);
```

## Performance

- **Overhead**: Minimal (async processing)
- **Memory**: ~50MB base + buffer
- **CPU**: Minimal (background timer)
- **Network**: Batched requests every 1s

## Troubleshooting

### Events not appearing in dashboard

1. Check `ingestUrl` is correct
2. Verify `apiKey` is valid
3. Check network connectivity
4. Look for errors in logs (use `onError` callback)

### High memory usage

- Reduce `bufferSize`
- Reduce `flushIntervalMs` to flush more frequently

### Disable instrumentation

```typescript
const observer = new ObserverClient({
  // ...
  enabled: false,
});
```

Or use environment variable:
```typescript
enabled: process.env.OBSERVER_ENABLED === 'true'
```

## License

MIT License - see [LICENSE](LICENSE) for details.

## Support

- GitHub Issues: [Report a bug](https://github.com/observer/nodejs-sdk/issues)
- Documentation: [docs/](docs/)