glockit
v1.0.3
Published
A TypeScript library for benchmarking REST APIs with request chaining capabilities
Maintainers
Readme
Glockit
Overview
Glockit is a lightweight TypeScript CLI and library for benchmarking REST APIs. It supports advanced request chaining, concurrent execution, variable extraction, and outputs results in JSON and CSV formats. The tool features a clean, dependency-minimal console interface for real-time progress tracking.
Table of Contents
- Installation
- Quick Start
- CLI Usage
- Programmatic Usage
- Configuration Reference
- Output Formats
- API Reference
- License
Features
- Configuration-driven: Define benchmarks in simple JSON files
- Real-time Progress Tracking: Clean console-based progress bars showing request status
- Request Chaining: Extract variables from responses and use them in subsequent requests
- Concurrent Execution: Run multiple requests in parallel with configurable concurrency
- Zero Dependencies: Built with minimal external dependencies for reliability
- Flexible Execution Modes: Supports both request-count and duration-based benchmarking
- Comprehensive Validation: Validates configuration with clear error messages
- Multi-format Output: Generates detailed JSON and CSV reports
- Security-conscious Logging: Sanitizes sensitive data in logs and outputs
Installation
Global Installation (Recommended for CLI usage)
npm install -g glockitLocal Installation (For programmatic usage)
npm install glockitQuick Start
- Create a
benchmark.jsonfile with your API endpoints:
{
"name": "E-Commerce API Benchmark",
"description": "Performance test for an e-commerce API workflow",
"global": {
"baseUrl": "https://api.example.com/v1",
"maxRequests": 100,
"concurrent": 10,
"timeout": 5000,
"requestDelay": 0,
"headers": {
"Content-Type": "application/json",
"Accept": "application/json"
}
},
"endpoints": [
{
"name": "User Login",
"url": "/auth/login",
"method": "POST",
"body": {
"email": "[email protected]",
"password": "test123"
},
"variables": [
{
"name": "authToken",
"path": "token",
"from": "response"
}
]
},
{
"name": "Get Products",
"url": "/products",
"method": "GET",
"headers": {
"Authorization": "Bearer {{authToken}}"
},
"dependencies": ["User Login"],
"variables": [
{
"name": "firstProductId",
"path": "products.0.id",
"from": "response"
}
]
},
{
"name": "Add to Cart",
"url": "/cart/items",
"method": "POST",
"headers": {
"Authorization": "Bearer {{authToken}}"
},
"body": {
"productId": "{{firstProductId}}",
"quantity": 1
},
"dependencies": ["Get Products"]
}
]
}- Run the benchmark:
npx glockit run --config benchmark.json --saveCLI Usage
glockit run [options]Options:
-c, --config <file>: Configuration file path (default: benchmark.json)-o, --output <dir>: Output directory for results (default: current directory)--no-progress: Disable progress bar-d, --delay <ms>: Delay between requests in milliseconds--save: Save results to files (JSON/CSV)
Programmatic Usage
import { Glockit, BenchmarkConfig } from 'glockit';
// Define your benchmark configuration
const config: BenchmarkConfig = {
name: 'API Performance Test',
global: {
baseUrl: 'https://api.example.com',
maxRequests: 50,
concurrent: 5,
timeout: 10000
},
endpoints: [
{
name: 'Health Check',
path: '/health',
method: 'GET'
},
{
name: 'Search Products',
path: '/products/search',
method: 'GET',
query: {
q: 'test',
limit: '10'
}
}
]
};
// Create a new benchmark instance
const benchmark = new Glockit({
progress: true, // Show progress bar (default: true)
delay: 100 // Delay between requests in ms (default: 0)
});
// Run the benchmark
async function runBenchmark() {
try {
console.log('🚀 Starting benchmark...');
// Run the benchmark
const results = await benchmark.run(config);
// Save results to files
await benchmark.saveResults(results, 'benchmark-results.json', 'benchmark-results.csv');
// Log summary
console.log('\n📊 Benchmark Results:');
console.log(`✅ Total Requests: ${results.summary.totalRequests}`);
console.log(`⏱️ Total Time: ${(results.summary.totalTime / 1000).toFixed(2)}s`);
console.log(`📈 Requests per Second: ${results.summary.requestsPerSecond.toFixed(2)}`);
console.log(`✅ Success Rate: ${(results.summary.successRate * 100).toFixed(2)}%`);
// Detailed results are available in the results object
console.log('\n🔍 Check benchmark-results.json and benchmark-results.csv for detailed results');
} catch (error) {
console.error('❌ Benchmark failed:', error);
process.exit(1);
}
}
runBenchmark();Configuration Reference
name(string): Benchmark namedescription(string): Descriptionglobal(object): Global settingsbaseUrl(string): Base URL for endpointsmaxRequests(number): Total requestsduration(number): Duration in msthrottle(number): Throttle rateconcurrent(number): Concurrent requeststimeout(number): Request timeoutrequestDelay(number): Delay between requests
endpoints(array): List of endpoint configsname(string): Endpoint nameurl(string): Endpoint path (relative to baseUrl)method(string): HTTP methodheaders(object): Request headersbody(object): Request bodymaxRequests,throttle,requestDelay: Endpoint-specific overridesvariables(array): Extract variables from response/headersdependencies(array): Endpoint dependencies
Variable Extraction
Extract values from responses to use in subsequent requests:
{
"variables": [
{
"name": "userId",
"path": "user.id",
"from": "response"
},
{
"name": "authHeader",
"path": "headers.authorization",
"from": "response"
}
]
}Example: Advanced Configuration
{
"name": "E-Commerce API Load Test",
"description": "Simulates a user flow through an e-commerce site",
"global": {
"baseUrl": "https://api.example.com/v1",
"maxRequests": 1000,
"concurrent": 50,
"timeout": 10000,
"headers": {
"Content-Type": "application/json",
"Accept": "application/json",
"X-Request-ID": "{{$uuid}}"
}
},
"endpoints": [
{
"name": "Homepage",
"url": "/home",
"method": "GET",
"weight": 3 // This endpoint will be called 3x more often than others
},
{
"name": "Search Products",
"url": "/products/search",
"method": "GET",
"query": {
"q": "{{$randomWord}}",
"page": "{{$randomInt(1, 5)}}",
"sort": "{{$randomFrom(['price', 'popularity', 'newest'])}}"
}
},
{
"name": "Product Detail",
"url": "/products/{{$randomFrom([1,2,3,4,5])}}",
"method": "GET"
},
{
"name": "Add to Cart",
"url": "/cart/items",
"method": "POST",
"headers": {
"Authorization": "Bearer {{authToken}}"
},
"body": {
"productId": "{{$randomUUID()}}",
"quantity": "{{$randomInt(1, 5)}}",
"color": "{{$randomFrom(['red', 'blue', 'green'])}}"
},
"dependencies": ["Login"]
}
]
}Output Formats
JSON Output
Detailed results including timing metrics, success rates, and error information:
{
"summary": {
"totalRequests": 100,
"totalTime": 1250,
"requestsPerSecond": 80.0,
"successRate": 0.98,
"totalErrors": 2,
"endpoints": {
"Login": {
"requests": 100,
"successful": 98,
"failed": 2,
"avgResponseTime": 45.2,
"minResponseTime": 12,
"maxResponseTime": 210,
"p50": 42,
"p90": 78,
"p95": 95,
"p99": 180
}
}
},
"errors": [
{
"endpoint": "Login",
"error": "Request timed out",
"timestamp": "2023-01-01T12:00:00.000Z"
}
]
}CSV Output
Tabular format suitable for analysis in spreadsheet software:
timestamp,endpoint,method,status,responseTime,contentLength
2023-01-01T12:00:00.000Z,Login,POST,200,45,128
2023-01-01T12:00:00.100Z,Get Products,GET,200,78,2048API Reference
Class: Glockit
Constructor
new Glockit(options?: {
progress?: boolean; // Show progress bar (default: true)
delay?: number; // Delay between requests in ms (default: 0)
})Methods
run(config: BenchmarkConfig): Promise
Run the benchmark with the given configuration.
saveResults(
results: BenchmarkResults, jsonFile: string, csvFile?: string ): Promise Save benchmark results to files.
generateExampleConfig(): BenchmarkConfig
Generate an example configuration object.
Types
interface BenchmarkConfig {
name?: string;
description?: string;
global: {
baseUrl?: string;
maxRequests: number;
concurrent: number;
timeout: number;
headers?: Record<string, string>;
};
endpoints: EndpointConfig[];
}
interface EndpointConfig {
name: string;
path?: string;
url?: string;
method?: string;
headers?: Record<string, string>;
body?: any;
query?: Record<string, string | number | boolean>;
variables?: VariableConfig[];
dependencies?: string[];
weight?: number;
}
interface VariableConfig {
name: string;
path: string;
from: 'response' | 'headers' | 'cookies';
}License
MIT © 2023 Glockit
