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

runtime-tracker

v2.0.0

Published

jest a timer for debug or performance tuning.

Readme

Runtime Tracker

A lightweight TypeScript library for hierarchical runtime performance tracking and debugging. Track execution times with nested steps and generate detailed timing reports.

npm version License: MIT

Overview

Runtime Tracker is designed to help developers measure and analyze the performance of their applications by providing hierarchical timing capabilities. It allows you to create nested timers that can track complex execution flows with multiple levels of granularity.

Key Features

  • Hierarchical Timing: Create nested timers to track multi-level execution flows
  • Tree-like Output: Generate human-readable timing reports with visual tree structure
  • JSON Export: Export timing data as structured JSON for further analysis
  • TypeScript Support: Full TypeScript support with comprehensive type definitions
  • Lightweight: Minimal dependencies and small footprint
  • Easy Integration: Simple API that can be easily integrated into existing codebases

Technical Architecture

Technology Stack

  • Language: TypeScript (compiled to ES5)
  • Module System: CommonJS
  • Dependencies:
    • numeral (^2.0.6) - Number formatting for readable time display
  • Development Dependencies:
    • typescript (^4.4.2) - TypeScript compiler
    • @types/numeral (^2.0.1) - Type definitions for numeral

Compilation Configuration

The project uses TypeScript with the following key settings:

  • Target: ES5 for broad compatibility
  • Module: CommonJS
  • Output: ./dist directory
  • Source Maps: Enabled for debugging
  • Decorators: Experimental decorators enabled

Project Structure

runtime-tracker/
├── src/
│   └── index.ts              # Main library source code
├── dist/                     # Compiled JavaScript output (generated)
├── .github/
│   └── prompts/              # Development prompts and instructions
├── package.json              # Project configuration and dependencies
├── tsconfig.json             # TypeScript compiler configuration
├── LICENSE                   # MIT License
├── README.md                 # Project documentation
└── .gitignore               # Git ignore rules

File System Structure Details

  • src/index.ts: Contains the main RuntimeTracker class and RuntimeLog interface
  • dist/: Auto-generated directory containing compiled JavaScript, type definitions, and source maps
  • package.json: Defines the library metadata, dependencies, and build scripts
  • tsconfig.json: TypeScript compiler configuration with ES5 target and CommonJS modules

Development Setup

Prerequisites

  • Node.js (version compatible with TypeScript 4.4.2+)
  • npm or yarn package manager

Installation

npm install runtime-tracker

Development Installation

git clone https://github.com/EJayCheng/runtime-tracker.git
cd runtime-tracker
npm install

Building

npm run prepublishOnly

This command compiles TypeScript to JavaScript and generates type definitions in the dist/ directory.

Code Quality Tools

TypeScript Configuration

The project uses strict TypeScript settings:

  • Source maps enabled for debugging
  • Declaration files generated automatically
  • Experimental decorators support
  • ES2016 and DOM libraries included

Linting and Formatting

Currently, the project relies on TypeScript's built-in type checking. Future contributors should maintain consistency with the existing code style:

  • Use meaningful variable and function names
  • Follow TypeScript naming conventions
  • Include proper type annotations
  • Write clear, self-documenting code

Environment Variables

This library does not require any environment variables for basic operation. It's designed to work in any JavaScript/TypeScript environment without external configuration.

Usage

Basic Usage

import { RuntimeTracker } from 'runtime-tracker';

// Create a new tracker
const tracker = new RuntimeTracker('MyOperation');

// Add some work
await someAsyncOperation();

// Create nested steps (manual management)
const step1 = tracker.step('Step1');
await someWork();
step1.end();

// Or use asyncStep for automatic management
await tracker.asyncStep('Step2', async () => {
  await moreWork();
  // Step2 will be automatically ended
});

// End the main tracker
tracker.end();

// Display results
console.log(tracker.toString());

Advanced Usage with Nested Steps

import { RuntimeTracker } from 'runtime-tracker';

const mainTracker = new RuntimeTracker('MainProcess');

// Create nested hierarchy
const dbOperations = mainTracker.step('DatabaseOperations');
const query1 = dbOperations.step('Query1');
await executeQuery1();
query1.end();

const query2 = dbOperations.step('Query2');
await executeQuery2();
query2.end();

dbOperations.end();

// Another main step
const processing = mainTracker.step('DataProcessing');
const validation = processing.step('Validation');
await validateData();
validation.end();

const transformation = processing.step('Transformation');
await transformData();
transformation.end();

processing.end();
mainTracker.end();

// Output tree structure
console.log(mainTracker.toString());
// [MainProcess]: 1,234 ms
//    ├ [DatabaseOperations]: 800 ms
//    │   ├ [Query1]: 300 ms
//    │   └ [Query2]: 500 ms
//    └ [DataProcessing]: 434 ms
//        ├ [Validation]: 134 ms
//        └ [Transformation]: 300 ms

Using asyncStep for Automatic Step Management

import { RuntimeTracker } from 'runtime-tracker';

const tracker = new RuntimeTracker('AsyncProcess');

// asyncStep automatically manages the step lifecycle
const userData = await tracker.asyncStep('FetchUserData', async () => {
  const response = await fetch('/api/user/123');
  return response.json();
});

// You can access the step tracker for nested operations
const processedData = await tracker.asyncStep(
  'ProcessData',
  async (stepTracker) => {
    // Use the step tracker to create nested operations
    const validated = await stepTracker.asyncStep('ValidateData', async () => {
      return validateUserData(userData);
    });

    const transformed = await stepTracker.asyncStep(
      'TransformData',
      async () => {
        return transformData(validated);
      },
    );

    return transformed;
  },
);

// Multiple async steps with nested tracking
await tracker.asyncStep('SaveToDatabase', async (dbTracker) => {
  await dbTracker.asyncStep('Connect', async () => {
    return database.connect();
  });

  await dbTracker.asyncStep('Insert', async () => {
    return database.save(processedData);
  });

  await dbTracker.asyncStep('Disconnect', async () => {
    return database.disconnect();
  });
});

await tracker.asyncStep('SendNotification', async () => {
  await notificationService.send('Data processed successfully');
});

tracker.end();

console.log(tracker.toString());
// [AsyncProcess]: 2,150 ms
//    ├ [FetchUserData]: 800 ms
//    ├ [ProcessData]: 650 ms
//    │   ├ [ValidateData]: 200 ms
//    │   └ [TransformData]: 450 ms
//    ├ [SaveToDatabase]: 400 ms
//    │   ├ [Connect]: 50 ms
//    │   ├ [Insert]: 300 ms
//    │   └ [Disconnect]: 50 ms
//    └ [SendNotification]: 300 ms

Advanced asyncStep with Deep Nesting

import { RuntimeTracker } from 'runtime-tracker';

const tracker = new RuntimeTracker('ComplexWorkflow');

const result = await tracker.asyncStep(
  'DataProcessingPipeline',
  async (pipeline) => {
    // Stage 1: Data Extraction
    const rawData = await pipeline.asyncStep(
      'DataExtraction',
      async (extraction) => {
        const apiData = await extraction.asyncStep('FetchFromAPI', async () => {
          return fetch('/api/data').then((r) => r.json());
        });

        const fileData = await extraction.asyncStep(
          'ReadFromFile',
          async () => {
            return readFileAsync('./data.json');
          },
        );

        return { apiData, fileData };
      },
    );

    // Stage 2: Data Validation & Cleaning
    const cleanData = await pipeline.asyncStep(
      'DataValidation',
      async (validation) => {
        const validatedApi = await validation.asyncStep(
          'ValidateAPI',
          async () => {
            return validateData(rawData.apiData);
          },
        );

        const validatedFile = await validation.asyncStep(
          'ValidateFile',
          async () => {
            return validateData(rawData.fileData);
          },
        );

        return await validation.asyncStep('MergeData', async () => {
          return mergeData(validatedApi, validatedFile);
        });
      },
    );

    // Stage 3: Data Transformation
    const transformedData = await pipeline.asyncStep(
      'DataTransformation',
      async (transform) => {
        return await transform.asyncStep('ApplyBusinessLogic', async () => {
          return applyBusinessRules(cleanData);
        });
      },
    );

    // Stage 4: Persistence
    await pipeline.asyncStep('DataPersistence', async (persistence) => {
      await persistence.asyncStep('SaveToDatabase', async () => {
        return database.bulkInsert(transformedData);
      });

      await persistence.asyncStep('UpdateCache', async () => {
        return cache.set('processed_data', transformedData);
      });

      await persistence.asyncStep('CreateBackup', async () => {
        return backup.save(transformedData);
      });
    });

    return transformedData;
  },
);

tracker.end();

console.log(tracker.toString());
// [ComplexWorkflow]: 3,450 ms
//    └ [DataProcessingPipeline]: 3,400 ms
//        ├ [DataExtraction]: 1,200 ms
//        │   ├ [FetchFromAPI]: 800 ms
//        │   └ [ReadFromFile]: 400 ms
//        ├ [DataValidation]: 900 ms
//        │   ├ [ValidateAPI]: 300 ms
//        │   ├ [ValidateFile]: 250 ms
//        │   └ [MergeData]: 350 ms
//        ├ [DataTransformation]: 600 ms
//        │   └ [ApplyBusinessLogic]: 600 ms
//        └ [DataPersistence]: 700 ms
//            ├ [SaveToDatabase]: 400 ms
//            ├ [UpdateCache]: 150 ms
//            └ [CreateBackup]: 150 ms

Export to JSON

const tracker = new RuntimeTracker('Process');
// ... perform operations ...
tracker.end();

const jsonData = tracker.toJSON();
console.log(JSON.stringify(jsonData, null, 2));

API Parameters and Configuration

RuntimeTracker Constructor

  • name: string - The name identifier for this tracker
  • upper?: RuntimeTracker - Optional parent tracker for nested hierarchy

Methods

  • step(name: string | RuntimeTracker): RuntimeTracker

    • Creates a new nested step tracker
    • Returns existing tracker if name already exists
    • Throws error if parent tracker is already ended
  • asyncStep<T>(name: string | RuntimeTracker, fn: (runtimeTracker?: RuntimeTracker) => Promise<T>): Promise<T>

    • Creates a new nested step tracker and executes an async function within its scope
    • Automatically ends the step tracker when the function completes (success or failure)
    • The function receives the created step tracker as an optional parameter for nested operations
    • Returns the result of the executed function
    • Perfect for tracking async operations like API calls, database queries, or file operations
    • Generic type T represents the return type of the async function
  • end(endAt?: number): void

    • Ends the tracker and all its children
    • endAt - Optional custom end timestamp (defaults to Date.now())
  • toString(space?: string, prefix?: string, isEndRow?: boolean): string

    • Generates formatted tree output
    • space - Indentation string (default: " ")
    • prefix - Line prefix for nested display
    • isEndRow - Whether this is the last item in its level
  • toJSON(): RuntimeLog

    • Exports tracker data as structured JSON
    • Includes timing data and nested step information

Testing

Currently, the project doesn't include a formal testing framework. Future contributors should consider:

  • Adding Jest or similar testing framework
  • Writing unit tests for all public methods
  • Testing edge cases like nested operations and error conditions
  • Performance testing for overhead measurements

Deployment

This is a npm library package with the following deployment characteristics:

Build Process

  • TypeScript compilation via tsc command
  • Generates CommonJS modules for broad compatibility
  • Creates declaration files for TypeScript consumers
  • Outputs to dist/ directory

Publishing

  • Published to npm registry (https://registry.npmjs.org/)
  • Version managed through package.json
  • Includes compiled JavaScript, type definitions, and source maps
  • Main entry point: dist/index.js
  • TypeScript definitions: dist/index.d.ts

Distribution Files

The published package includes:

  • Compiled JavaScript (ES5-compatible)
  • TypeScript declaration files
  • Source maps for debugging
  • Package metadata

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Ensure TypeScript compilation succeeds
  5. Submit a pull request

Links