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 🙏

© 2025 – Pkg Stats / Ryan Hefner

rivia-logs

v1.7.1

Published

Rivia Logs library

Downloads

820

Readme

Rivia Logs

A comprehensive and secure JavaScript logging library built on Bunyan with advanced data masking capabilities and recursive field protection for sensitive information.

🚀 Features

  • Custom Field Protection: Configure custom sensitive fields per logger instance
  • Runtime Masking: Apply field masking per individual log call
  • Case-Insensitive: Automatically handles camelCase, UPPERCASE, and UpperFirst transformations
  • Production Ready: Built on battle-tested Bunyan logging framework
  • Zero Configuration: Works out-of-the-box with sensible defaults
  • Environment Aware: Configurable via environment variables

📦 Installation

npm install rivia-logs

🎯 Quick Start

Basic Usage

There are two ways of using this logging library

1. Creating a simple logger

const { logger } = require('rivia-logs');

// Create a simple logger
const log = logger('my-app');

// Log with automatic sensitive data masking
log.info({
  user: '[email protected]',
  password: 'secret123',      // ✅ Automatically masked
  token: 'abc-xyz-123',       // ✅ Automatically masked
  publicData: 'visible'       // ✅ Remains visible
}, 'User login attempt');


// Debug logging
log.debug('Debug info', { details: 'debugging data' });

// Error logging
log.error(err, 'An error occurred');

2. Using global logging functions directly

const { info, debug, error } = require('rivia-logs');

// Global logging functions
info('Application started', { 
  version: '1.0.0',
  authorization: 'Bearer xyz'  // ✅ Automatically masked
});

// Debug logging
debug({ details: 'debugging data' }, 'Debug info');

// Error logging
error('An error occurred', { error: 'Error message' });

🚨 Important: Pay attention to the fact that these two implementation methods differ from each other. Below you can find more details about each usage approach.

🔒 Data Masking Features

Default Sensitive Fields

The library automatically masks these fields (case-insensitive):

  • password / Password / PASSWORD
  • token / Token / TOKEN
  • authorization / Authorization / AUTHORIZATION
  • senha / Senha / SENHA (Portuguese for password)

Custom Field Masking

const { logger, info } = require('rivia-logs');

// Method 1 - Step 1: Configure in logger constructor
const authLogger = logger({
  name: 'auth-service',
  customMaskFields: ['refreshToken', 'sessionId', 'apiSecret']
});

// Method 1 - Step 2: Using custom logger
authLogger.info({
  refreshToken: 'refresh-abc-123',    // ✅ Masked
  sessionId: 'sess-xyz-789',          // ✅ Masked
  userId: 'user-456'                  // ✅ Visible
}, 'User session created');

// Method 2: Runtime masking with global functions
info('API request', {
  endpoint: '/api/users',
  apiKey: 'secret-key-123',           // ✅ Masked via options
  response: 'success'                 // ✅ Visible
}, { maskFields: ['apiKey'] });

Field Transformations

Custom fields automatically handle all case variations:

const log = logger({ customMaskFields: ['customField'] });

log.info({
  customField: 'secret1',    // ✅ Masked
  customfield: 'visible',    // ✅ Visible (different field)
  CUSTOMFIELD: 'secret2',    // ✅ Masked (uppercase transform)
  CustomField: 'secret3'     // ✅ Masked (upperFirst transform)
});

📝 API Reference

Logger Creation

// Simple logger with default name
const log = logger();

// Logger with custom name
const log = logger('my-service');

// Logger with full configuration
const log = logger({
  name: 'payment-service',
  customMaskFields: ['creditCard', 'ssn']
});

Global Functions

// Basic usage
info(message, data, options, loggerName);
debug(message, data, options, loggerName);
error(message, data, options, loggerName);

// Examples
info('User action', { userId: 'abc123' });
debug('Debug data', { details: 'info' }, {}, 'debug-logger');
error('Error occurred', { error: 'failed' }, { maskFields: ['customField'] });

Options Object

const options = {
  maskFields: ['field1', 'field2']  // Additional fields to mask for this log entry
};

info('Message', data, options);

⚙️ Configuration

Environment Variables

# Set default logger name
export LOGGER_NAME=my-application

# Set logging level (trace, debug, info, warn, error, fatal)
export LOGGER_LEVEL=info

Log Levels

const log = logger('my-app');

log.trace('Trace level');    // Most verbose
log.debug('Debug info');     // Development info
log.info('Information');     // General info
log.warn('Warning');         // Warning messages
log.error('Error');          // Error messages
log.fatal('Fatal error');    // Critical errors

🛡️ Security Features

Automatic Protection

// These are automatically protected regardless of nesting level (up to 3 deep)
const sensitiveData = {
  user: {
    auth: {
      password: 'secret123',        // ✅ Masked
      authorization: 'Bearer xyz',  // ✅ Masked
      token: 'access-token',        // ✅ Masked
      senha: 'senha123'             // ✅ Masked
    }
  }
};

🧪 Real-World Examples

API Service Logging

const { logger } = require('rivia-logs');

class APIService {
  constructor() {
    this.log = logger({
      name: 'api-service',
      customMaskFields: ['apiKey', 'clientSecret']
    });
  }

  async authenticateUser(credentials) {
    this.log.info({
      action: 'authenticate',
      username: credentials.username,
      password: credentials.password,      // ✅ Automatically masked
      apiKey: credentials.apiKey,          // ✅ Masked via customMaskFields
      timestamp: new Date().toISOString()
    }, 'User authentication attempt');

    try {
      const result = await this.processAuth(credentials);
      
      this.log.info({
        result: 'success',
        userId: result.userId,
        token: result.token                // ✅ Automatically masked
      }, 'Authentication successful');
      
      return result;
    } catch (error) {
      this.log.error({
        error: error.message,
        stack: error.stack,
        credentials: credentials             // ✅ Sensitive fields will be masked
      }, 'Authentication failed');
      
      throw error;
    }
  }
}

Payment Processing

const { logger, info } = require('rivia-logs');

const paymentLog = logger({
  name: 'payment-processor',
  customMaskFields: ['cardNumber', 'cvv', 'ssn']
});

function processPayment(paymentData) {
  paymentLog.info({
    orderId: paymentData.orderId,
    amount: paymentData.amount,
    cardNumber: paymentData.cardNumber,    // ✅ Masked
    cvv: paymentData.cvv,                  // ✅ Masked
    customerInfo: {
      email: paymentData.email,
      ssn: paymentData.ssn                 // ✅ Masked (nested)
    }
  }, 'Processing payment');

  // Using global function with runtime masking
  info('Gateway request', {
    gateway: 'stripe',
    merchantId: 'merch_123',
    secretKey: 'sk_test_xyz123'            // ✅ Masked via options
  }, { maskFields: ['secretKey'] }, 'payment-gateway');
}