Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pinchtab/pinchtab/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Metrics API provides performance and resource usage data for:
  • Server-level metrics (requests, latency, memory)
  • Tab-level metrics (JS heap, DOM nodes, listeners)
  • Instance metrics (memory usage per instance)

Get Server Metrics

Retrieve server-wide performance metrics.
GET /metrics
curl http://localhost:9867/metrics | jq .

Response (200 OK)

{
  "requestsTotal": 1245,
  "requestsFailed": 12,
  "avgLatencyMs": 125.5,
  "rateLimited": 0,
  "staleRefRetries": 8,
  "rateBucketHosts": 15,
  "goHeapAllocMB": 45.32,
  "goHeapSysMB": 67.89,
  "goNumGoroutine": 23,
  "goHeapObjects": 234567,
  "goGCPauseNs": 150000,
  "goNumGC": 45
}

Response Fields

requestsTotal
integer
required
Total API requests served
requestsFailed
integer
required
Number of failed requests
avgLatencyMs
number
required
Average request latency in milliseconds
rateLimited
integer
required
Number of rate-limited requests
staleRefRetries
integer
required
Number of automatic retries due to stale element references
rateBucketHosts
integer
required
Number of hosts being tracked for rate limiting
goHeapAllocMB
number
required
Go heap memory allocated in MB
goHeapSysMB
number
required
Go heap memory obtained from OS in MB
goNumGoroutine
integer
required
Number of active goroutines
goHeapObjects
integer
required
Number of objects allocated on heap
goGCPauseNs
integer
required
Last garbage collection pause in nanoseconds
goNumGC
integer
required
Number of completed GC cycles

Get Tab Metrics

Retrieve memory and performance metrics for a specific tab.
GET /tabs/{id}/metrics
curl http://localhost:9867/tabs/tab_abc123/metrics | jq .

Response (200 OK)

{
  "jsHeapUsedMB": 25.6,
  "jsHeapTotalMB": 48.3,
  "documents": 1,
  "frames": 3,
  "nodes": 1458,
  "listeners": 234
}

Response Fields

jsHeapUsedMB
number
required
JavaScript heap memory in use (MB)
jsHeapTotalMB
number
required
Total JavaScript heap memory allocated (MB)
documents
integer
required
Number of documents
frames
integer
required
Number of frames (including iframes)
nodes
integer
required
Number of DOM nodes
listeners
integer
required
Number of event listeners

Monitoring Example

import requests
import time

BASE = "http://localhost:9867"

def monitor_server(interval_seconds=30):
    """Monitor server metrics"""
    while True:
        resp = requests.get(f"{BASE}/metrics")
        m = resp.json()
        
        print(f"\n--- Server Metrics ---")
        print(f"Requests: {m['requestsTotal']} ({m['requestsFailed']} failed)")
        print(f"Avg Latency: {m['avgLatencyMs']:.2f}ms")
        print(f"Heap: {m['goHeapAllocMB']:.2f}MB / {m['goHeapSysMB']:.2f}MB")
        print(f"Goroutines: {m['goNumGoroutine']}")
        print(f"GC Pause: {m['goGCPauseNs'] / 1000000:.2f}ms")
        
        time.sleep(interval_seconds)

# Start monitoring
monitor_server(30)

Tab Memory Tracking

def track_tab_memory(tab_id, duration_seconds=60, interval=5):
    """Track tab memory over time"""
    import time
    
    measurements = []
    start_time = time.time()
    
    while time.time() - start_time < duration_seconds:
        resp = requests.get(f"http://localhost:9867/tabs/{tab_id}/metrics")
        m = resp.json()
        
        measurements.append({
            "timestamp": time.time(),
            "heapUsed": m["jsHeapUsedMB"],
            "nodes": m["nodes"],
            "listeners": m["listeners"]
        })
        
        print(f"Heap: {m['jsHeapUsedMB']:.2f}MB | Nodes: {m['nodes']} | Listeners: {m['listeners']}")
        
        time.sleep(interval)
    
    return measurements

# Track memory for 60 seconds
data = track_tab_memory("tab_abc123", duration_seconds=60, interval=5)

# Analyze
max_heap = max(m["heapUsed"] for m in data)
avg_nodes = sum(m["nodes"] for m in data) / len(data)

print(f"\nMax heap: {max_heap:.2f}MB")
print(f"Avg nodes: {avg_nodes:.0f}")

Memory Leak Detection

def detect_memory_leak(tab_id, url, iterations=10):
    """Detect potential memory leaks by repeated navigation"""
    import time
    
    heap_sizes = []
    
    for i in range(iterations):
        # Navigate
        requests.post(f"http://localhost:9867/tabs/{tab_id}/navigate",
            json={"url": url, "waitFor": "networkidle"})
        
        time.sleep(2)
        
        # Get metrics
        resp = requests.get(f"http://localhost:9867/tabs/{tab_id}/metrics")
        heap = resp.json()["jsHeapUsedMB"]
        heap_sizes.append(heap)
        
        print(f"Iteration {i+1}: {heap:.2f}MB")
    
    # Analyze trend
    if heap_sizes[-1] > heap_sizes[0] * 1.5:
        print("\n⚠️  Potential memory leak detected!")
        print(f"Initial: {heap_sizes[0]:.2f}MB")
        print(f"Final: {heap_sizes[-1]:.2f}MB")
        print(f"Increase: {((heap_sizes[-1] / heap_sizes[0]) - 1) * 100:.1f}%")
    else:
        print("\n✓ No significant memory growth")
    
    return heap_sizes

# Test for memory leaks
detect_memory_leak("tab_abc123", "https://example.com", iterations=10)

Performance Dashboard Example

import requests
import time
from datetime import datetime

BASE = "http://localhost:9867"

def performance_dashboard():
    """Display real-time performance dashboard"""
    while True:
        # Clear screen
        print("\033[2J\033[H")
        
        # Server metrics
        server = requests.get(f"{BASE}/metrics").json()
        
        print("=" * 60)
        print(f"PinchTab Performance Dashboard - {datetime.now().strftime('%H:%M:%S')}")
        print("=" * 60)
        
        print("\n📊 Server Metrics:")
        print(f"  Total Requests:    {server['requestsTotal']:,}")
        print(f"  Failed Requests:   {server['requestsFailed']:,}")
        success_rate = (1 - server['requestsFailed'] / max(server['requestsTotal'], 1)) * 100
        print(f"  Success Rate:      {success_rate:.2f}%")
        print(f"  Avg Latency:       {server['avgLatencyMs']:.2f}ms")
        
        print("\n💾 Memory:")
        print(f"  Heap Allocated:    {server['goHeapAllocMB']:.2f}MB")
        print(f"  Heap System:       {server['goHeapSysMB']:.2f}MB")
        print(f"  Heap Objects:      {server['goHeapObjects']:,}")
        
        print("\n⚙️  Runtime:")
        print(f"  Goroutines:        {server['goNumGoroutine']}")
        print(f"  GC Cycles:         {server['goNumGC']}")
        print(f"  Last GC Pause:     {server['goGCPauseNs'] / 1000000:.2f}ms")
        
        # Get all tabs
        tabs = requests.get(f"{BASE}/tabs").json()
        
        print(f"\n📑 Active Tabs: {len(tabs)}")
        
        for tab in tabs[:5]:  # Show first 5 tabs
            try:
                metrics = requests.get(f"{BASE}/tabs/{tab['id']}/metrics").json()
                print(f"  {tab['id'][:12]}: {metrics['jsHeapUsedMB']:.1f}MB | {metrics['nodes']} nodes")
            except:
                pass
        
        print("\n" + "=" * 60)
        print("Press Ctrl+C to exit")
        
        time.sleep(5)

# Run dashboard
try:
    performance_dashboard()
except KeyboardInterrupt:
    print("\nDashboard stopped")

Alerting Example

import requests
import time

HEAP_THRESHOLD_MB = 100
NODE_THRESHOLD = 5000

def monitor_with_alerts(tab_id):
    """Monitor tab and alert on high resource usage"""
    while True:
        resp = requests.get(f"http://localhost:9867/tabs/{tab_id}/metrics")
        m = resp.json()
        
        # Check heap usage
        if m["jsHeapUsedMB"] > HEAP_THRESHOLD_MB:
            print(f"⚠️  HIGH HEAP USAGE: {m['jsHeapUsedMB']:.2f}MB")
            # Could send email, Slack notification, etc.
        
        # Check DOM node count
        if m["nodes"] > NODE_THRESHOLD:
            print(f"⚠️  HIGH DOM NODE COUNT: {m['nodes']}")
        
        # Check listener count (potential leak indicator)
        if m["listeners"] > m["nodes"]:
            print(f"⚠️  MORE LISTENERS THAN NODES: {m['listeners']} listeners, {m['nodes']} nodes")
        
        time.sleep(10)

# Start monitoring
monitor_with_alerts("tab_abc123")

Best Practices

Monitor Regularly

# ✅ Good: Regular monitoring
def run_task_with_monitoring(tab_id):
    # Check metrics before
    before = requests.get(f"{BASE}/tabs/{tab_id}/metrics").json()
    
    # Run task
    do_work(tab_id)
    
    # Check metrics after
    after = requests.get(f"{BASE}/tabs/{tab_id}/metrics").json()
    
    # Alert if significant increase
    if after["jsHeapUsedMB"] > before["jsHeapUsedMB"] * 2:
        print("Warning: Heap doubled during task")

Set Thresholds

THRESHOLDS = {
    "jsHeapUsedMB": 150,
    "nodes": 10000,
    "listeners": 5000
}

def check_thresholds(tab_id):
    metrics = requests.get(f"{BASE}/tabs/{tab_id}/metrics").json()
    
    for key, threshold in THRESHOLDS.items():
        if metrics[key] > threshold:
            print(f"⚠️  {key} exceeded threshold: {metrics[key]} > {threshold}")

Log Metrics

import json
from datetime import datetime

def log_metrics(tab_id, log_file="metrics.jsonl"):
    """Log metrics to file"""
    metrics = requests.get(f"http://localhost:9867/tabs/{tab_id}/metrics").json()
    metrics["timestamp"] = datetime.now().isoformat()
    
    with open(log_file, "a") as f:
        f.write(json.dumps(metrics) + "\n")

Use Cases

Performance Testing

Monitor resource usage during load tests:
# Before test
initial = requests.get(f"{BASE}/metrics").json()

# Run load test
run_load_test()

# After test
final = requests.get(f"{BASE}/metrics").json()

print(f"Requests processed: {final['requestsTotal'] - initial['requestsTotal']}")
print(f"Avg latency: {final['avgLatencyMs']:.2f}ms")

Memory Profiling

Track memory usage patterns:
# Profile page memory over time
measurements = track_tab_memory(tab_id, duration_seconds=300, interval=10)

# Analyze
import matplotlib.pyplot as plt
plt.plot([m["heapUsed"] for m in measurements])
plt.title("Tab Memory Usage Over Time")
plt.ylabel("Heap (MB)")
plt.xlabel("Measurement")
plt.show()

Health Checks

Monitor server health:
def health_check():
    metrics = requests.get("http://localhost:9867/metrics").json()
    
    # Check if healthy
    if metrics["requestsFailed"] / max(metrics["requestsTotal"], 1) > 0.1:
        return False, "High failure rate"
    
    if metrics["goHeapAllocMB"] > 500:
        return False, "High memory usage"
    
    if metrics["goNumGoroutine"] > 1000:
        return False, "Too many goroutines"
    
    return True, "Healthy"

Next Steps

Instances API

Monitor instance performance

Tabs API

Track tab resource usage

Screencast

Visual monitoring

Health Check

Server health endpoint