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

@universal-kit/metrics-client

v0.1.15

Published

OpenTelemetry-based metrics HTTP client wrapper with API provider monitoring and enhanced tracing

Readme

@universal-kit/metrics-client

OpenTelemetry-based metrics HTTP client wrapper with API provider monitoring and enhanced tracing for universal-kit. This package provides both a Node fetch-based client and an Axios-compatible wrapper with comprehensive provider-level metrics and detailed request tracing.

Installation

npm install @universal-kit/metrics-client axios

Features

  • OpenTelemetry Integration: Full OpenTelemetry metrics and tracing support
  • API Provider Monitoring: Measure latency and success rates per provider
  • API Key Usage Tracking: Track usage by provider, API key, path, and status
  • Path Normalization: Automatically normalize dynamic path segments to reduce metric cardinality
  • Enhanced Request Tracing: Detailed request events and span tracking
  • Failed Request Analysis: Comprehensive logging and tracing of failed requests
  • Axios Compatibility: Drop-in replacement for existing Axios code
  • TypeScript Support: Full TypeScript support with proper type definitions
  • Request/Response Size Tracking: Automatic size measurement for monitoring
  • Configurable Logging: Integration with universal-kit logger

Usage

NodeFetchWrapper (Node Fetch-based)

import { NodeFetchWrapper } from '@universal-kit/metrics-client';

const client = new NodeFetchWrapper({
  baseUrl: 'https://api.example.com',
  timeout: 5000,
  headers: {
    Authorization: 'Bearer your-token',
  },
  // Provider monitoring configuration
  provider: 'my-api-provider',
  apiKey: 'your-api-key',
  apiKeyHeader: 'x-api-key', // Custom API key header
  traceFailedRequests: true,
  logRequestEvents: true,
});

// Make a measured request with provider tracking
try {
  const result = await client.get<User>('/users/1');
  console.log('Data:', result.data);
  console.log('Metrics:', result.metrics);

  // Get provider success rate
  const successRate = client.getProviderSuccessRate();
  console.log('Provider success rate:', successRate);
} catch (error) {
  console.error('Request failed:', error);
}

AxiosWrapper (Axios-compatible)

import {
  AxiosWrapper,
  AxiosWrapperRequestConfig,
} from '@universal-kit/metrics-client';

const config: AxiosWrapperRequestConfig = {
  provider: 'payment-provider',
  apiKey: 'pk_live_1234567890',
  apiKeyHeader: 'x-api-key',
  baseURL: 'https://api.example.com',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json',
  },
  traceFailedRequests: true,
  logRequestEvents: true,
};

const axiosClient = new AxiosWrapper(config);

// Use as drop-in replacement for Axios with provider monitoring
try {
  const response = await axiosClient.get<User>('/users/1');
  console.log('Data:', response.data);
  console.log('Metrics:', response._metrics); // Axios response with enhanced metrics

  // Access provider metrics
  const providerMetrics = axiosClient.getProviderMetricsManager();
  const requestTracer = axiosClient.getRequestTracer();
} catch (error) {
  console.error('Request failed:', error);
  console.error('Metrics:', error._metrics); // Error with detailed metrics
}

// Custom API key extraction from headers
const customAxios = new AxiosWrapper({
  provider: 'custom-api',
  getApiKey: config => {
    // Custom logic to extract API key from headers or config
    return config.headers?.['custom-auth-key'] || 'default-key';
  },
  apiKeyHeader: 'custom-auth-key',
});

Advanced Axios Usage

import { AxiosWrapper } from '@universal-kit/metrics-client';

const client = new AxiosWrapper();

// Configure base URL
client.setConfig({
  baseUrl: 'https://api.example.com',
  headers: { 'Content-Type': 'application/json' },
});

// Use all Axios methods
const getUsers = await client.get('/users');
const createUser = await client.post('/users', { name: 'John' });
const updateUser = await client.put('/users/1', { name: 'Jane' });
const patchUser = await client.patch('/users/1', { status: 'active' });
const deleteUser = await client.delete('/users/1');

// Custom request configuration
const config: AxiosWrapperRequestConfig = {
  method: 'GET',
  url: '/custom',
  skipMetrics: true, // Skip metrics for this request
  headers: { 'X-Custom': 'value' },
};
const customResponse = await client.request(config);

// Access underlying Axios instance for advanced usage
const axiosInstance = client.getAxiosInstance();
axiosInstance.interceptors.request.use(config => {
  // Custom interceptor logic
  return config;
});

Path Normalization

Path normalization automatically converts dynamic path segments (IDs, UUIDs, hashes, addresses) into parameterized templates to prevent unbounded metric cardinality. This is crucial for maintaining efficient metrics storage and query performance.

Basic Pattern-Based Normalization

import { AxiosWrapper } from '@universal-kit/metrics-client';

const client = new AxiosWrapper({
  provider: 'my-api',
  pathNormalization: {
    enabled: true,
  },
});

// Automatic normalization examples:
// /users/12345/orders/67890          → /users/:path1/orders/:path2
// /orders/550e8400-e29b-41d4-...     → /orders/:path1
// /api/v1/health                     → /api/v1/health (preserved)

Crypto-Specific Pattern Detection

Enable crypto-specific patterns to detect blockchain addresses and transaction hashes:

const client = new AxiosWrapper({
  provider: 'blockchain-api',
  pathNormalization: {
    enabled: true,
    enableCryptoPatterns: true, // Detect Solana, Ethereum addresses, etc.
  },
});

// Normalization examples with crypto patterns:
// /defi/quotation/v1/smartmoney/sol/walletNew/L43t5u52tHCFG...
//   → /defi/quotation/v1/smartmoney/sol/walletNew/:path1
//
// /api/v1/wallet_stat/base/0x799f27d36fa00edae8663e7fee25e839331645a8/7d
//   → /api/v1/wallet_stat/base/:path1/7d

OpenAPI Spec-Based Normalization

Use OpenAPI specifications for accurate path normalization with preserved parameter names:

const client = new AxiosWrapper({
  provider: 'my-api',
  pathNormalization: {
    enabled: true,
    openApiSpecs: [
      {
        path: './openapi.json', // Load from file
        domain: 'api.example.com',
      },
      {
        url: 'https://api.other.com/openapi.yaml', // Load from URL
        domain: 'api.other.com',
      },
    ],
  },
});

// With OpenAPI spec defining /users/{userId}/orders/{orderId}:
// /users/12345/orders/67890  → /users/:userId/orders/:orderId (preserved names)
//
// Without matching spec:
// /products/abc123           → /products/:path1 (generic fallback)

Manual Spec Refresh

Refresh OpenAPI specs at runtime (useful for dynamic spec updates):

const client = new AxiosWrapper({
  provider: 'my-api',
  pathNormalization: {
    enabled: true,
    openApiSpecs: [{ path: './openapi.json', domain: 'api.example.com' }],
  },
});

// Later, refresh specs (e.g., after deployment)
await client.refreshOpenApiSpecs();

Supported Pattern Types

Pattern-based normalization detects:

  • UUIDs: 550e8400-e29b-41d4-a716-446655440000:path1
  • Numeric IDs: 12345:path2
  • Base58: Solana addresses, Bitcoin addresses → :path3
  • Hex Hashes: 0xabcdef123456...:path4
  • MongoDB ObjectIds: 507f1f77bcf86cd799439011:path5
  • Ethereum Addresses (with enableCryptoPatterns): 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb
  • Transaction Hashes (with enableCryptoPatterns): 0x8a8eafb1cf62...

Migration Guide

Enabling path normalization changes the path label in metrics. To migrate:

  1. Enable for new deployments first:

    pathNormalization: {
      enabled: true;
    }
  2. Monitor metric cardinality before/after to validate improvements

  3. Update dashboards to use normalized paths:

    • Old: path="/users/12345/orders/67890"
    • New: path="/users/:path1/orders/:path2"
  4. Use OpenAPI specs for accurate parameter names in production

API Provider Monitoring

import {
  NodeFetchWrapper,
  AxiosWrapper,
  ProviderMetricsManager,
} from '@universal-kit/metrics-client';

// Create client with provider monitoring
const client = new AxiosWrapper({
  provider: 'payment-api',
  apiKey: 'your-api-key',
  baseURL: 'https://api.example.com',
  enableMetrics: true,
});

// Get provider metrics manager
const metricsManager = client.getProviderMetricsManager();

// Access provider-level analytics
const successRate = metricsManager.getProviderSuccessRate();
const requestCount = metricsManager.getProviderRequestCount();
const errorRate = metricsManager.getProviderErrorRate();

// Get detailed metrics by API key
const apiKeyMetrics = metricsManager.getApiKeyMetrics();

// Access request tracer for detailed request information
const tracer = client.getRequestTracer();

// Make requests and collect metrics
await client.get('/users/1');
await client.get('/users/2');

// Get updated metrics after requests
console.log('Updated success rate:', metricsManager.getProviderSuccessRate());
console.log('Total requests:', metricsManager.getProviderRequestCount());

Available provider-level metrics:

  • Request count per provider
  • Success rate calculation
  • Error rate tracking
  • API key-specific metrics
  • Request/response timing
  • Status code distribution
  • Error tracking and analysis

Error Handling

import { AxiosWrapper } from '@universal-kit/metrics-client';

const client = new AxiosWrapper();

try {
  const response = await client.get('/nonexistent');
} catch (error: any) {
  // Access metrics even on errors
  console.log('Error metrics:', error._metrics);

  // Handle different error types
  if (error.response) {
    // Server responded with error status
    console.log('Status:', error.response.status);
    console.log('Data:', error.response.data);
  } else if (error.request) {
    // Request was made but no response received
    console.log('Network error:', error.message);
  } else {
    // Something else happened
    console.log('Error:', error.message);
  }
}

Configuration Options

Both NodeFetchWrapper and AxiosWrapper support comprehensive configuration:

interface BaseWrapperConfig {
  baseUrl?: string;
  timeout?: number;
  headers?: Record<string, string>;
  enableMetrics?: boolean;
  provider?: string;
  apiKey?: string;
  apiKeyHeader?: string;
  getApiKey?: (config: any) => string;
  traceFailedRequests?: boolean;
  logRequestEvents?: boolean;
  redactedHeaders?: string[]; // Headers to redact in logs and traces
  pathNormalization?: {
    enabled: boolean;
    openApiSpecs?: Array<{
      path?: string; // File path to OpenAPI spec
      url?: string; // URL to OpenAPI spec
      domain: string; // Domain to match for this spec
    }>;
    enableCryptoPatterns?: boolean; // Detect crypto addresses/hashes
  };
}

interface AxiosWrapperRequestConfig extends BaseWrapperConfig {
  // All Axios config options supported
  baseURL?: string;
  method?: string;
  data?: any;
  params?: any;
  skipMetrics?: boolean;
}

API Reference

NodeFetchWrapper

Constructor

new NodeFetchWrapper(config?: BaseWrapperConfig, logger?: Logger)

Methods

  • get<T>(url, config?) - GET request
  • post<T>(url, data?, config?) - POST request
  • put<T>(url, data?, config?) - PUT request
  • patch<T>(url, data?, config?) - PATCH request
  • delete<T>(url, config?) - DELETE request
  • request<T>(config) - Custom request

AxiosWrapper

Constructor

new AxiosWrapper(config?: BaseWrapperConfig, logger?: Logger)

Methods

  • get<T>(url, config?) - Axios-compatible GET request
  • post<T>(url, data?, config?) - Axios-compatible POST request
  • put<T>(url, data?, config?) - Axios-compatible PUT request
  • patch<T>(url, data?, config?) - Axios-compatible PATCH request
  • delete<T>(url, config?) - Axios-compatible DELETE request
  • request<T>(config) - Axios-compatible custom request

Properties

  • defaults - Axios defaults
  • interceptors - Axios interceptors

Utility Methods

  • setConfig(config) - Update configuration
  • getConfig() - Get current configuration
  • getAxiosInstance() - Get underlying Axios instance
  • getProviderMetricsManager() - Get provider metrics manager
  • getRequestTracer() - Get request tracer
  • refreshOpenApiSpecs() - Manually refresh OpenAPI specifications for path normalization

ProviderMetricsManager

  • getProviderSuccessRate() - Get success rate for provider
  • getProviderRequestCount() - Get total request count
  • getProviderErrorRate() - Get error rate for provider
  • getApiKeyMetrics() - Get metrics by API key
  • resetMetrics() - Reset all metrics

RequestTracer

  • traceRequest(request, response) - Trace a request
  • traceError(request, error) - Trace an error
  • getActiveSpans() - Get active request spans
  • getRequestTrace(requestId) - Get trace by request ID

Key Features

  • Provider-Level Monitoring: Track usage per API provider with success rates and analytics
  • OpenTelemetry Integration: Full OTel metrics and tracing support for enterprise observability
  • Request Tracing: Detailed request lifecycle tracking with comprehensive error analysis
  • Axios Compatibility: Drop-in replacement for existing Axios code with enhanced features
  • Node Fetch Support: Native Node.js fetch wrapper for modern applications
  • API Key Tracking: Monitor usage by API key, path, and status code
  • TypeScript Support: Full TypeScript support with proper type definitions
  • Metrics Access: Access detailed metrics from responses and errors
  • Configurable Logging: Integration with universal-kit logger
  • Request/Response Size Tracking: Track HTTP request and response sizes
  • Failed Request Analysis: Comprehensive logging and tracing of failed requests

Examples

Production-ready Setup

import { AxiosWrapper } from '@universal-kit/metrics-client';
import { Logger } from '@universal-kit/logger';

// Initialize logger
const logger = new Logger({
  level: 'info',
  service: 'my-service',
});

// Create HTTP client with provider monitoring
const httpClient = new AxiosWrapper(
  {
    provider: 'payment-provider',
    apiKey: process.env.PAYMENT_API_KEY,
    apiKeyHeader: 'x-api-key',
    baseURL: 'https://api.payment-provider.com',
    timeout: 10000,
    traceFailedRequests: true,
    logRequestEvents: true,
    enableMetrics: true,
  },
  logger
);

// Use in your application
export { httpClient };