npm package: @reasonable-logging/js-sdk
Description: Official JavaScript SDK for Reasonable logging platform
Author: entwicklerstube ug
Latest version: 1.0.1

# 🚀 @reasonable-logging/js-sdk

> **The official JavaScript SDK for Reasonable** - Simple, powerful logging and event tracking for modern applications.

[![npm version](https://badge.fury.io/js/@reasonable-logging%2Fjs-sdk.svg)](https://badge.fury.io/js/@reasonable-logging%2Fjs-sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)

## ✨ Features

- 🎯 **Simple & Intuitive** - Get started in minutes with our clean API
- 🏗️ **TypeScript First** - Built with full TypeScript support and type safety
- 🔥 **Lightweight** - Zero dependencies, minimal bundle size
- 🚀 **Performance** - Optimized for speed with batching and async operations
- 🛡️ **Reliable** - Comprehensive error handling and retry logic
- 📊 **Rich Metadata** - Attach custom metadata to every log and event
- 🎨 **Flexible** - Works in Node.js, browsers, and edge environments
- 🔍 **Developer Experience** - Child loggers, global metadata, and more

## 📦 Installation

```bash
npm install @reasonable-logging/js-sdk
```

```bash
yarn add @reasonable-logging/js-sdk
```

```bash
pnpm add @reasonable-logging/js-sdk
```

## 🚀 Quick Start

```typescript
import { ReasonableLogger } from '@reasonable-logging/js-sdk';

// Initialize the logger
const logger = new ReasonableLogger({
  projectId: 'your-project-id',
  apiKey: 'your-api-key',
  application: 'my-awesome-app'
});

// Start logging!
await logger.info('User logged in', { userId: '123', plan: 'pro' });
await logger.error('Payment failed', { error: 'card_declined', amount: 99.99 });

// Track custom events
await logger.userEvent('signup', 'user-123', { plan: 'pro', source: 'organic' });
await logger.businessEvent('purchase', { amount: 99.99, plan: 'pro' });
```

## 📖 API Reference

### Constructor

```typescript
const logger = new ReasonableLogger({
  projectId: string,      // Your Reasonable project ID
  apiKey: string,         // Your API key
  baseUrl?: string,       // Custom API endpoint (optional, defaults to https://reasonable.sh)
  application?: string,   // Application name (optional)
  timeout?: number        // Request timeout in ms (default: 5000)
});
```

### Logging Methods

All logging methods return a `Promise<LogResponse>` and accept optional metadata.

#### 📝 Basic Logging

```typescript
// Log levels: debug, info, warn, error, fatal
await logger.debug('Debug message', { context: 'debugging' });
await logger.info('User action', { userId: '123', action: 'click' });
await logger.warn('Rate limit approaching', { current: 95, limit: 100 });
await logger.error('Database error', { query: 'SELECT *', error: 'timeout' });
await logger.fatal('System crash', { exitCode: 1, reason: 'out_of_memory' });
```

#### 📊 Event Tracking

```typescript
// User events (signup, login, logout, etc.)
await logger.userEvent('signup', 'user-123', { 
  plan: 'pro', 
  source: 'organic',
  campaign: 'summer2024'
});

// Business events (purchase, conversion, etc.)
await logger.businessEvent('purchase', { 
  amount: 99.99, 
  currency: 'USD',
  plan: 'pro',
  paymentMethod: 'card'
});

// Performance events (load times, response times, etc.)
await logger.performanceEvent('page_load', { 
  loadTime: 1250,
  route: '/dashboard',
  browser: 'Chrome'
});

// Custom events (anything else!)
await logger.customEvent('feature_used', { 
  feature: 'dark_mode',
  enabled: true,
  userId: 'user-123'
});
```

### 🌟 Advanced Features

#### Global Metadata

Set metadata that will be included with every log entry:

```typescript
logger.setGlobalMeta({
  version: '2.1.0',
  environment: 'production',
  region: 'us-west-2',
  buildId: 'abc123'
});

// Now every log will include this metadata automatically
await logger.info('User action'); // Includes version, environment, etc.
```

#### Child Loggers

Create specialized loggers with their own context:

```typescript
// Create a child logger for a specific component
const authLogger = logger.child({ component: 'auth', module: 'login' });

// All logs from this child will include the component and module context
await authLogger.info('Login attempt', { email: 'user@example.com' });
await authLogger.error('Login failed', { reason: 'invalid_password' });

// Create child loggers for different users
const userLogger = logger.child({ userId: 'user-123', plan: 'pro' });
await userLogger.info('Profile updated');
```

## 🏗️ Framework Integration

### React

```jsx
import React, { useEffect } from 'react';
import { ReasonableLogger } from '@reasonable-logging/js-sdk';

const logger = new ReasonableLogger({
  projectId: process.env.REACT_APP_REASONABLE_PROJECT_ID,
  apiKey: process.env.REACT_APP_REASONABLE_API_KEY,
  application: 'my-react-app'
});

function App() {
  useEffect(() => {
    // Set browser context
    logger.setGlobalMeta({
      userAgent: navigator.userAgent,
      url: window.location.href,
      timestamp: new Date().toISOString()
    });

    logger.info('App initialized');
  }, []);

  const handleClick = async () => {
    await logger.userEvent('button_click', undefined, { 
      button: 'cta',
      page: 'home'
    });
  };

  return <button onClick={handleClick}>Click me!</button>;
}
```

### Node.js/Express

```javascript
const express = require('express');
const { ReasonableLogger } = require('@reasonable-logging/js-sdk');

const app = express();
const logger = new ReasonableLogger({
  projectId: process.env.REASONABLE_PROJECT_ID,
  apiKey: process.env.REASONABLE_API_KEY,
  application: 'my-api'
});

// Middleware to add request context
app.use((req, res, next) => {
  req.logger = logger.child({
    requestId: req.headers['x-request-id'],
    userAgent: req.headers['user-agent'],
    ip: req.ip,
    method: req.method,
    path: req.path
  });
  next();
});

app.get('/api/users', async (req, res) => {
  try {
    await req.logger.info('Fetching users');
    const users = await getUsers();
    
    await req.logger.info('Users fetched successfully', { 
      count: users.length 
    });
    
    res.json(users);
  } catch (error) {
    await req.logger.error('Failed to fetch users', { 
      error: error.message 
    });
    res.status(500).json({ error: 'Internal server error' });
  }
});
```

### Next.js

```typescript
// lib/logger.ts
import { ReasonableLogger } from '@reasonable-logging/js-sdk';

export const logger = new ReasonableLogger({
  projectId: process.env.NEXT_PUBLIC_REASONABLE_PROJECT_ID!,
  apiKey: process.env.REASONABLE_API_KEY!,
  application: 'my-nextjs-app'
});

// pages/api/users.ts
import { logger } from '../../lib/logger';

export default async function handler(req, res) {
  const requestLogger = logger.child({
    requestId: req.headers['x-request-id'],
    method: req.method,
    url: req.url
  });

  try {
    await requestLogger.info('API request started');
    // Your API logic here
    await requestLogger.info('API request completed');
    res.status(200).json({ success: true });
  } catch (error) {
    await requestLogger.error('API request failed', { error: error.message });
    res.status(500).json({ error: 'Internal server error' });
  }
}
```

## 🔧 Configuration

### Environment Variables

For security, we recommend using environment variables:

```bash
# .env
REASONABLE_PROJECT_ID=your-project-id
REASONABLE_API_KEY=your-api-key
REASONABLE_BASE_URL=https://your-custom-domain.com  # optional
```

### TypeScript Configuration

The SDK is built with TypeScript and provides full type safety:

```typescript
import { ReasonableLogger, LogData, EventData, LogResponse } from '@reasonable-logging/js-sdk';

// All types are exported for your convenience
const logData: LogData = {
  level: 'INFO',
  message: 'Typed log entry',
  meta: { typed: true }
};

const response: LogResponse = await logger.log(logData);
```

## 🚨 Error Handling

The SDK handles errors gracefully and provides detailed error information:

```typescript
try {
  await logger.info('This might fail');
} catch (error) {
  console.error('Logging failed:', error.message);
  // Your app continues to work normally
}

// Or handle errors in the response
const response = await logger.info('Safe logging');
if (!response.success) {
  console.error('Log failed:', response.error);
}
```

## 🎯 Best Practices

### 1. Use Environment-Specific Loggers

```typescript
// Create different loggers for different environments
const logger = new ReasonableLogger({
  projectId: process.env.NODE_ENV === 'production' 
    ? 'prod-project-id' 
    : 'dev-project-id',
  apiKey: process.env.REASONABLE_API_KEY,
  application: `my-app-${process.env.NODE_ENV}`
});
```

### 2. Structure Your Metadata

```typescript
// Consistent metadata structure
await logger.info('User action', {
  // User context
  userId: 'user-123',
  email: 'user@example.com',
  
  // Action context  
  action: 'profile_update',
  section: 'settings',
  
  // Technical context
  version: '2.1.0',
  platform: 'web',
  browser: 'Chrome'
});
```

### 3. Use Child Loggers for Components

```typescript
// Create specialized loggers
const authLogger = logger.child({ component: 'auth' });
const paymentLogger = logger.child({ component: 'payment' });
const analyticsLogger = logger.child({ component: 'analytics' });

// Each maintains its own context
await authLogger.info('Login successful');
await paymentLogger.error('Payment failed');
await analyticsLogger.info('Event tracked');
```

### 4. Log Business Events

```typescript
// Track important business metrics
await logger.businessEvent('user_signup', {
  plan: 'pro',
  source: 'organic',
  revenue: 29.99,
  trial: false
});

await logger.businessEvent('feature_used', {
  feature: 'advanced_search',
  plan: 'enterprise',
  userId: 'user-123'
});
```

## 📊 Monitoring & Observability

### Performance Tracking

```typescript
// Track application performance
const startTime = Date.now();

try {
  await someExpensiveOperation();
  
  await logger.performanceEvent('operation_completed', {
    duration: Date.now() - startTime,
    operation: 'data_export',
    recordCount: 1500
  });
} catch (error) {
  await logger.error('Operation failed', {
    duration: Date.now() - startTime,
    operation: 'data_export',
    error: error.message
  });
}
```

### User Journey Tracking

```typescript
// Track user flow through your application
await logger.userEvent('page_view', userId, { page: 'landing' });
await logger.userEvent('cta_click', userId, { cta: 'sign_up', page: 'landing' });
await logger.userEvent('form_start', userId, { form: 'signup' });
await logger.userEvent('form_complete', userId, { form: 'signup', duration: 45 });
await logger.userEvent('signup_success', userId, { plan: 'pro' });
```

## 🔗 API Endpoints

The SDK communicates with these Reasonable API endpoints:

- **Logs**: `POST /api/v1/logs` - Send log entries
- **Events**: `POST /api/v1/events` - Send custom events

## 🛠️ Development

```bash
# Clone the repository
git clone https://github.com/reasonable-logging/reasonable.git
cd reasonable/sdk/js

# Install dependencies
npm install

# Run tests
npm test

# Build the project
npm run build

# Watch mode for development
npm run dev
```

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.

## 📝 License

MIT © [entwicklerstube ug (haftungsbeschränkt)](https://reasonable.dev)

## 🆘 Support

- 📖 **Documentation**: [https://docs.reasonable.dev](https://docs.reasonable.dev)
- 📧 **Email**: [support@reasonable.dev](mailto:support@reasonable.dev)
- 🐛 **Issues**: [GitHub Issues](https://github.com/reasonable-logging/reasonable/issues)

---

<div align="center">
  <strong>Made with ❤️ by entwicklerstube ug (haftungsbeschränkt)</strong>
</div>