Skip to content

Instantly share code, notes, and snippets.

@mikecarroll
Last active August 20, 2025 15:13
Show Gist options
  • Select an option

  • Save mikecarroll/f6882e57bba8eda89c85b491b74e3d89 to your computer and use it in GitHub Desktop.

Select an option

Save mikecarroll/f6882e57bba8eda89c85b491b74e3d89 to your computer and use it in GitHub Desktop.
A lightweight Node.js script that automatically captures and logs all OpenAI API calls made by your application without requiring code changes.
// monitor.js - Enhanced debug version
const fs = require('fs');
const https = require('https');
const http = require('http');
class CoolHandLlmMonitor {
constructor(options = {}) {
this.outputFile = options.outputFile || 'api_calls.jsonl';
this.callCounter = 0;
this.interceptedCalls = 0;
// Simple logging configuration - just one variable
this.silent = options.silent !== false; // Default: false (verbose)
if (!this.silent) {
console.log('πŸ” Setting up CoolHandLlmMonitor...');
}
this.setupMonitoring();
if (!this.silent) {
console.log('βœ… CoolHandLlmMonitor ready - will log to:', this.outputFile);
}
}
log(...args) {
if (!this.silent) {
console.log(...args);
}
}
setupMonitoring() {
// Patch HTTPS
this.patchHTTPS();
// Patch HTTP (some libraries might use HTTP with upgrade)
this.patchHTTP();
// Patch fetch if available (Node 18+)
this.patchFetch();
// Debug: Log when any request happens
this.log('πŸ“‘ Monitoring all outbound requests...');
}
patchHTTPS() {
const originalRequest = https.request;
const originalGet = https.get;
const monitor = this;
https.request = function(options, callback) {
monitor.debugRequest('HTTPS REQUEST', options);
// Check if this is an OpenAI call
const isOpenAI = monitor.isOpenAICall(options);
if (isOpenAI) {
monitor.log('🎯 INTERCEPTING OpenAI HTTPS call');
return monitor.interceptRequest(originalRequest, options, callback, 'https');
}
return originalRequest.call(this, options, callback);
};
https.get = function(options, callback) {
monitor.debugRequest('HTTPS GET', options);
const isOpenAI = monitor.isOpenAICall(options);
if (isOpenAI) {
monitor.log('🎯 INTERCEPTING OpenAI HTTPS GET');
return monitor.interceptRequest(originalRequest, options, callback, 'https');
}
return originalGet.call(this, options, callback);
};
}
patchHTTP() {
const originalRequest = http.request;
const originalGet = http.get;
const monitor = this;
http.request = function(options, callback) {
monitor.debugRequest('HTTP REQUEST', options);
if (isOpenAI) {
monitor.log('🎯 INTERCEPTING OpenAI HTTP call');
return monitor.interceptRequest(originalRequest, options, callback, 'http');
}
return originalRequest.call(this, options, callback);
};
http.get = function(options, callback) {
monitor.debugRequest('HTTP GET', options);
const isOpenAI = monitor.isOpenAICall(options);
if (isOpenAI) {
monitor.log('🎯 INTERCEPTING OpenAI HTTP GET');
return monitor.interceptRequest(originalRequest, options, callback, 'http');
}
return originalGet.call(this, options, callback);
};
}
patchFetch() {
if (typeof globalThis.fetch === 'function') {
const originalFetch = globalThis.fetch;
const monitor = this;
globalThis.fetch = async function(url, options = {}) {
const urlStr = typeof url === 'string' ? url : url.toString();
monitor.debugRequest('FETCH', { url: urlStr, ...options });
if (urlStr.includes('openai.com')) {
monitor.log('🎯 INTERCEPTING OpenAI FETCH call');
return monitor.interceptFetch(originalFetch, url, options);
}
return originalFetch.call(this, url, options);
};
}
}
isOpenAICall(options) {
if (typeof options === 'string') {
return options.includes('openai.com');
}
const hostname = options.hostname || options.host || '';
const href = options.href || '';
const path = options.path || '';
return hostname.includes('openai.com') ||
href.includes('openai.com') ||
path.includes('openai.com');
}
debugRequest(type, options) {
const hostname = options.hostname || options.host || options.url || 'unknown';
this.log(`🌐 ${type} to: ${hostname}`);
// Count all requests
this.callCounter++;
}
interceptRequest(originalRequest, options, callback, protocol) {
this.interceptedCalls++;
const url = this.buildURL(options, protocol);
const callData = {
id: this.interceptedCalls,
timestamp: new Date().toISOString(),
method: options.method || 'GET',
url: url,
headers: this.sanitizeHeaders(options.headers || {}),
request_body: null,
response_body: null,
response_headers: null,
status_code: null,
protocol: protocol
};
this.log(`πŸ“ž Starting API call #${callData.id} to ${url}`);
let requestBody = '';
const req = originalRequest.call(protocol === 'https' ? https : http, options, (res) => {
monitor.log(`πŸ“₯ Response received for call #${callData.id}, status: ${res.statusCode}`);
let responseBody = '';
res.on('data', (chunk) => {
responseBody += chunk.toString();
});
res.on('end', () => {
callData.response_body = monitor.parseJSON(responseBody);
callData.response_headers = monitor.sanitizeHeaders(res.headers);
callData.status_code = res.statusCode;
monitor.logCall(callData);
});
if (callback) callback(res);
});
// Intercept request body
const originalWrite = req.write.bind(req);
const originalEnd = req.end.bind(req);
req.write = function(chunk, encoding) {
if (chunk) {
requestBody += chunk.toString();
monitor.log(`πŸ“€ Request body chunk: ${chunk.toString().substring(0, 100)}...`);
}
return originalWrite(chunk, encoding);
};
req.end = function(chunk, encoding) {
if (chunk) {
requestBody += chunk.toString();
}
callData.request_body = monitor.parseJSON(requestBody);
monitor.log(`πŸ“€ Request complete for call #${callData.id}`);
return originalEnd(chunk, encoding);
};
req.on('error', (err) => {
monitor.log(`❌ Request error for call #${callData.id}:`, err.message);
});
return req;
}
async interceptFetch(originalFetch, url, options) {
this.interceptedCalls++;
const callData = {
id: this.interceptedCalls,
timestamp: new Date().toISOString(),
method: options.method || 'GET',
url: url.toString(),
headers: this.sanitizeHeaders(options.headers || {}),
request_body: options.body ? this.parseJSON(options.body) : null,
response_body: null,
response_headers: null,
status_code: null,
protocol: 'fetch'
};
this.log(`πŸ“ž Starting FETCH call #${callData.id} to ${url}`);
try {
const response = await originalFetch.call(globalThis, url, options);
callData.status_code = response.status;
callData.response_headers = Object.fromEntries(response.headers.entries());
// Clone response to read body without consuming it
const responseClone = response.clone();
const responseText = await responseClone.text();
callData.response_body = this.parseJSON(responseText);
this.logCall(callData);
return response;
} catch (error) {
this.log(`❌ Fetch error for call #${callData.id}:`, error.message);
throw error;
}
}
buildURL(options, protocol) {
if (options.href) return options.href;
const hostname = options.hostname || options.host || 'unknown';
const path = options.path || '/';
const port = options.port ? `:${options.port}` : '';
return `${protocol}://${hostname}${port}${path}`;
}
sanitizeHeaders(headers) {
const sanitized = { ...headers };
if (sanitized.authorization) {
sanitized.authorization = sanitized.authorization.replace(/Bearer .+/, 'Bearer [REDACTED]');
}
if (sanitized['openai-api-key']) {
sanitized['openai-api-key'] = '[REDACTED]';
}
if (sanitized['api-key']) {
sanitized['api-key'] = '[REDACTED]';
}
return sanitized;
}
parseJSON(str) {
if (!str) return null;
try {
return JSON.parse(str);
} catch {
return str;
}
}
logCall(callData) {
// Always write to file
const logEntry = JSON.stringify(callData, null, 2) + '\n' + '='.repeat(80) + '\n';
fs.appendFileSync(this.outputFile, logEntry);
// Console output (only if not silent)
if (!this.silent) {
console.log(`\nπŸŽ‰ LOGGED OpenAI API Call #${callData.id}`);
console.log(`πŸ• Time: ${callData.timestamp}`);
console.log(`🎯 ${callData.method} ${callData.url}`);
console.log(`πŸ“Š Status: ${callData.status_code}`);
console.log(`πŸ”§ Protocol: ${callData.protocol}`);
if (callData.request_body?.model) {
console.log(`πŸ€– Model: ${callData.request_body.model}`);
}
if (callData.request_body?.messages) {
console.log(`πŸ’¬ Messages: ${callData.request_body.messages.length}`);
}
if (callData.request_body?.temperature !== undefined) {
console.log(`🌑️ Temperature: ${callData.request_body.temperature}`);
}
console.log(`πŸ“ Logged to: ${this.outputFile}`);
console.log('═'.repeat(60));
}
}
getStats() {
return {
totalRequests: this.callCounter,
interceptedCalls: this.interceptedCalls
};
}
}
// Auto-start monitoring with default options
const monitor = new CoolHandLlmMonitor();
// Export both the instance and the constructor
module.exports = monitor;
module.exports.CoolHandLlmMonitor = CoolHandLlmMonitor;
// Add a test function
monitor.test = function() {
this.log('πŸ§ͺ CoolHandLlmMonitor test - stats:', this.getStats());
return 'CoolHandLlmMonitor is active';
};
if (!monitor.silent) {
console.log('✨ CoolHandLlmMonitor loaded! Test with: require("./monitor").test()');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment