Stagehand provides comprehensive logging capabilities to help you debug automation workflows, track execution, and diagnose issues. Configure logging levels, structured output, and debugging tools for both development and production environments.
Logs can be sent to different destinations, including your console and external observability platforms:
Pino (Default)
Console Fallback
Custom Logger
External Logger (Production)
Fast, structured, colorized JSON logger with console output.When to use: Development, staging, or production without external observability; can manage multiple Stagehand instances
Copy
Ask AI
// Enabled by default - Pino handles console output automaticallyconst stagehand = new Stagehand({ verbose: 1, // restOfYourConfiguration...});
Why auto-disable? Pino uses worker threads for pretty-printing, which can cause issues in test runners.
Your custom logging function to receive all logs. Works independently of Pino - receives logs regardless of Pino setting.When to use: Development, debugging, or when you don’t need querying
capabilities.
1
Create a simple logger
Copy
Ask AI
// Simple logger without parsing (for basic console output)const simpleLogger = (logLine: LogLine) => { console.log(`[${logLine.level}] ${logLine.message}`); // Optional: log raw auxiliary data if (logLine.auxiliary) { console.log(' Context:', logLine.auxiliary); }};
Your custom logging function to receive all logs. Works independently of Pino - receives logs regardless of Pino setting.When to use: Production with DataDog, Sentry, CloudWatch, or custom observability platforms for centralized monitoring and enable error alerting. Here’s examples using Sentry and DataDog:
1
Create a production logger
Sentry
DataDog
Copy
Ask AI
import * as Sentry from "@sentry/node";const productionLogger = (logLine: LogLine) => { // Send errors to Sentry if (logLine.level === 0) { Sentry.captureMessage(logLine.message, { level: 'error', extra: aux, }); }}// Helper to parse auxiliary data to be flat, numeric, and filterablefunction parseAuxiliary(aux?: LogLine['auxiliary']): Record<string, any> { if (!aux) return {}; const parsed: Record<string, any> = {}; for (const [key, entry] of Object.entries(aux)) { parsed[key] = entry.type === 'object' ? JSON.parse(entry.value) : entry.value; } return parsed;}
Copy
Ask AI
import { datadogLogs } from "@datadog/browser-logs";const productionLogger = (logLine: LogLine) => { // Send all logs to DataDog datadogLogs.logger.log(logLine.message, { status: logLine.level === 0 ? 'error' : 'info', service: 'stagehand-automation', category: logLine.category, ...aux, });}// Helper to parse auxiliary data to be flat, numeric, and filterablefunction parseAuxiliary(aux?: LogLine['auxiliary']): Record<string, any> { if (!aux) return {}; const parsed: Record<string, any> = {}; for (const [key, entry] of Object.entries(aux)) { parsed[key] = entry.type === 'object' ? JSON.parse(entry.value) : entry.value; } return parsed;}