npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@reasonable-logging/js-sdk

v1.0.1

Published

Official JavaScript SDK for Reasonable logging platform

Readme

🚀 @reasonable-logging/js-sdk

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

npm version License: MIT TypeScript

✨ 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

npm install @reasonable-logging/js-sdk
yarn add @reasonable-logging/js-sdk
pnpm add @reasonable-logging/js-sdk

🚀 Quick Start

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

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

// 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

// 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:

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:

// 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: '[email protected]' });
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

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

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

// 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:

# .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:

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:

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

// 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

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

3. Use Child Loggers for Components

// 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

// 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

// 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

// 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

# 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 for details.

📝 License

MIT © entwicklerstube ug (haftungsbeschränkt)

🆘 Support