Skip to content

Consolidate console logging to structured logger utility#935

Merged
pranaygp merged 3 commits intomainfrom
pranaygp/improved-logging
Feb 5, 2026
Merged

Consolidate console logging to structured logger utility#935
pranaygp merged 3 commits intomainfrom
pranaygp/improved-logging

Conversation

@pranaygp
Copy link
Collaborator

@pranaygp pranaygp commented Feb 4, 2026

Summary

  • Replace all console.log, console.warn, and console.error calls in packages/core/src with the structured logger utility from logger.ts
  • Fix logger to always output error/warn to console - Previously errors were silently swallowed unless DEBUG env var was set
  • Fix log levels - Downgrade warnings that are really info (expected states), downgrade errors that are really warnings (transient failures with retry)
  • Remove verbose debug logs from hot paths (events-consumer)

Log Level Changes

Message Before After Reason
OpenTelemetry not available warn info Expected in many environments
Workflow already completed, skipping warn info Normal state
Step/wait already exists, continuing warn info Idempotency case
Workflow run already completed, skipping step/hook warn info Race condition, normal
Step invoked erroneously error warn Handled gracefully
Encountered Error, step will be retried error warn Transient, will retry
Encountered RetryableError warn warn Unchanged (correct)
Step exceeded max retries error error Unchanged (correct)
FatalError in step error error Unchanged (correct)
Error while running workflow error error Unchanged (correct)

Test plan

  • Build passes (pnpm build in packages/core)
  • All 304 tests pass (pnpm test in packages/core)
  • Verified error/warn logs now output to console with [Workflow] prefix
  • Verified no remaining raw console. calls in source files (only logger.ts and JSDoc examples)

🤖 Generated with Claude Code

Replace all console.log, console.warn, and console.error calls in
packages/core/src with the structured logger utility from logger.ts.
This provides consistent, filterable logging with OpenTelemetry
integration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 4, 2026 21:23
@vercel
Copy link
Contributor

vercel bot commented Feb 4, 2026

@changeset-bot
Copy link

changeset-bot bot commented Feb 4, 2026

🦋 Changeset detected

Latest commit: 7c9d7c9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 15 packages
Name Type
@workflow/core Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/docs-typecheck Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/web-shared Patch
workflow Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/world-testing Patch
@workflow/nuxt Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Feb 4, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 479 0 38 517
✅ 💻 Local Development 438 0 32 470
✅ 📦 Local Production 438 0 32 470
✅ 🐘 Local Postgres 438 0 32 470
✅ 🪟 Windows 47 0 0 47
❌ 🌍 Community Worlds 31 169 0 200
✅ 📋 Other 129 0 12 141
Total 2000 169 146 2315

❌ Failed Tests

🌍 Community Worlds (169 failed)

mongodb (42 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • readableStreamWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • outputStreamWorkflow
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

redis (42 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • readableStreamWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • outputStreamWorkflow
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

starter (43 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • readableStreamWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • outputStreamWorkflow
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • health check (CLI) - workflow health command reports healthy endpoints
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

turso (42 failed):

  • addTenWorkflow
  • addTenWorkflow
  • should work with react rendering in step
  • promiseAllWorkflow
  • promiseRaceWorkflow
  • promiseAnyWorkflow
  • readableStreamWorkflow
  • hookWorkflow
  • webhookWorkflow
  • sleepingWorkflow
  • nullByteWorkflow
  • workflowAndStepMetadataWorkflow
  • outputStreamWorkflow
  • outputStreamInsideStepWorkflow - getWritable() called inside step functions
  • fetchWorkflow
  • promiseRaceStressTestWorkflow
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • hookCleanupTestWorkflow - hook token reuse after workflow completion
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars)
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument
  • closureVariableWorkflow - nested step functions with closure variables
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly
  • Calculator.calculate - static workflow method using static step methods from another class
  • AllInOneService.processNumber - static workflow method using sibling static step methods
  • ChainableService.processWithThis - static step methods using this to reference the class
  • thisSerializationWorkflow - step function invoked with .call() and .apply()
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE
  • instanceMethodStepWorkflow - instance methods with "use step" directive
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 43 0 4
✅ example 43 0 4
✅ express 43 0 4
✅ fastify 43 0 4
✅ hono 43 0 4
✅ nextjs-turbopack 46 0 1
✅ nextjs-webpack 46 0 1
✅ nitro 43 0 4
✅ nuxt 43 0 4
✅ sveltekit 43 0 4
✅ vite 43 0 4
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 43 0 4
✅ express-stable 43 0 4
✅ fastify-stable 43 0 4
✅ hono-stable 43 0 4
✅ nextjs-turbopack-stable 47 0 0
✅ nextjs-webpack-stable 47 0 0
✅ nitro-stable 43 0 4
✅ nuxt-stable 43 0 4
✅ sveltekit-stable 43 0 4
✅ vite-stable 43 0 4
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 43 0 4
✅ express-stable 43 0 4
✅ fastify-stable 43 0 4
✅ hono-stable 43 0 4
✅ nextjs-turbopack-stable 47 0 0
✅ nextjs-webpack-stable 47 0 0
✅ nitro-stable 43 0 4
✅ nuxt-stable 43 0 4
✅ sveltekit-stable 43 0 4
✅ vite-stable 43 0 4
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 43 0 4
✅ express-stable 43 0 4
✅ fastify-stable 43 0 4
✅ hono-stable 43 0 4
✅ nextjs-turbopack-stable 47 0 0
✅ nextjs-webpack-stable 47 0 0
✅ nitro-stable 43 0 4
✅ nuxt-stable 43 0 4
✅ sveltekit-stable 43 0 4
✅ vite-stable 43 0 4
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 47 0 0
❌ 🌍 Community Worlds
App Passed Failed Skipped
✅ mongodb-dev 3 0 0
❌ mongodb 5 42 0
✅ redis-dev 3 0 0
❌ redis 5 42 0
✅ starter-dev 3 0 0
❌ starter 4 43 0
✅ turso-dev 3 0 0
❌ turso 5 42 0
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 43 0 4
✅ e2e-local-postgres-nest-stable 43 0 4
✅ e2e-local-prod-nest-stable 43 0 4

📋 View full workflow run

@github-actions
Copy link
Contributor

github-actions bot commented Feb 4, 2026

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 0.032s (-29.6% 🟢) 1.018s (~) 0.987s 10 1.00x
💻 Local Express 0.043s (-3.6%) 1.008s (~) 0.965s 10 1.36x
💻 Local Nitro 0.044s (+2.8%) 1.008s (~) 0.964s 10 1.38x
🐘 Postgres Nitro 0.196s (-7.8% 🟢) 1.015s (~) 0.818s 10 6.19x
🐘 Postgres Express 0.233s (-4.4%) 1.013s (~) 0.780s 10 7.36x
🐘 Postgres Next.js (Turbopack) 0.269s (-29.4% 🟢) 1.030s (+0.8%) 0.762s 10 8.47x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.780s (-0.9%) 1.602s (-7.1% 🟢) 0.822s 10 1.00x
▲ Vercel Nitro 0.790s (+10.1% 🔺) 1.614s (-8.3% 🟢) 0.824s 10 1.01x
▲ Vercel Next.js (Turbopack) 1.223s (+42.2% 🔺) 2.240s (+27.7% 🔺) 1.017s 10 1.57x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 1.087s (~) 2.012s (~) 0.924s 10 1.00x
💻 Local Nitro 1.114s (~) 2.008s (~) 0.893s 10 1.02x
💻 Local Express 1.119s (~) 2.007s (~) 0.888s 10 1.03x
🐘 Postgres Next.js (Turbopack) 1.837s (-1.6%) 2.016s (-4.7%) 0.179s 10 1.69x
🐘 Postgres Express 2.189s (-1.7%) 3.015s (~) 0.826s 10 2.01x
🐘 Postgres Nitro 2.336s (-4.2%) 3.016s (~) 0.680s 10 2.15x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.941s (-5.2% 🟢) 3.807s (-1.5%) 0.867s 10 1.00x
▲ Vercel Express 2.945s (+2.4%) 3.802s (+1.8%) 0.857s 10 1.00x
▲ Vercel Nitro 2.948s (-2.3%) 3.697s (-3.7%) 0.749s 10 1.00x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 10.569s (-1.3%) 11.018s (~) 0.449s 3 1.00x
💻 Local Nitro 10.818s (~) 11.014s (~) 0.195s 3 1.02x
💻 Local Express 10.833s (~) 11.014s (~) 0.181s 3 1.02x
🐘 Postgres Next.js (Turbopack) 14.537s (-2.7%) 15.035s (-3.1%) 0.498s 2 1.38x
🐘 Postgres Nitro 20.441s (+0.6%) 21.036s (~) 0.595s 2 1.93x
🐘 Postgres Express 20.505s (~) 21.033s (~) 0.529s 2 1.94x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 22.599s (-3.3%) 23.253s (-3.5%) 0.654s 2 1.00x
▲ Vercel Next.js (Turbopack) 23.230s (-2.4%) 23.890s (-2.6%) 0.660s 2 1.03x
▲ Vercel Nitro 23.816s (-1.8%) 25.024s (-0.7%) 1.208s 2 1.05x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 26.858s (-1.4%) 27.026s (-3.6%) 0.168s 3 1.00x
💻 Local Nitro 27.447s (~) 28.028s (~) 0.581s 3 1.02x
💻 Local Express 27.484s (~) 28.026s (~) 0.543s 3 1.02x
🐘 Postgres Next.js (Turbopack) 34.968s (-5.1% 🟢) 35.557s (-5.4% 🟢) 0.589s 2 1.30x
🐘 Postgres Nitro 50.310s (~) 51.087s (~) 0.776s 2 1.87x
🐘 Postgres Express 50.411s (~) 51.065s (~) 0.653s 2 1.88x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 56.506s (-5.0% 🟢) 57.646s (-4.2%) 1.140s 2 1.00x
▲ Vercel Nitro 57.748s (-3.2%) 58.636s (-3.2%) 0.888s 2 1.02x
▲ Vercel Express 58.274s (-3.4%) 59.239s (-3.2%) 0.965s 2 1.03x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 55.651s (-1.7%) 56.040s (-1.8%) 0.388s 2 1.00x
💻 Local Nitro 57.103s (~) 58.037s (~) 0.933s 2 1.03x
💻 Local Express 57.194s (~) 58.045s (~) 0.851s 2 1.03x
🐘 Postgres Next.js (Turbopack) 69.502s (-6.0% 🟢) 69.603s (-6.1% 🟢) 0.101s 2 1.25x
🐘 Postgres Nitro 100.122s (~) 100.146s (-1.0%) 0.024s 1 1.80x
🐘 Postgres Express 100.229s (~) 101.134s (~) 0.905s 1 1.80x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 119.676s (-2.4%) 120.574s (-2.2%) 0.898s 1 1.00x
▲ Vercel Nitro 119.902s (~) 120.679s (~) 0.777s 1 1.00x
▲ Vercel Next.js (Turbopack) 120.556s (-0.7%) 121.248s (-1.1%) 0.692s 1 1.01x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 1.364s (-1.6%) 2.011s (~) 0.647s 15 1.00x
💻 Local Express 1.401s (-1.9%) 2.006s (~) 0.605s 15 1.03x
💻 Local Nitro 1.403s (-1.0%) 2.006s (~) 0.603s 15 1.03x
🐘 Postgres Next.js (Turbopack) 2.038s (~) 2.533s (-2.8%) 0.495s 12 1.49x
🐘 Postgres Nitro 2.267s (-2.7%) 3.014s (~) 0.747s 10 1.66x
🐘 Postgres Express 2.334s (~) 2.685s (-11.0% 🟢) 0.351s 12 1.71x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.989s (-3.7%) 3.835s (+0.9%) 0.846s 8 1.00x
▲ Vercel Nitro 3.009s (~) 3.904s (-0.9%) 0.895s 8 1.01x
▲ Vercel Express 3.147s (+9.9% 🔺) 4.019s (+4.7%) 0.873s 8 1.05x

🔍 Observability: Next.js (Turbopack) | Nitro | Express

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 2.292s (-8.9% 🟢) 3.231s (+5.9% 🔺) 0.939s 10 1.00x
💻 Local Nitro 2.539s (-1.0%) 3.015s (~) 0.476s 10 1.11x
💻 Local Express 2.572s (-0.9%) 3.017s (~) 0.445s 10 1.12x
🐘 Postgres Nitro 8.459s (+2.5%) 9.049s (~) 0.591s 4 3.69x
🐘 Postgres Express 10.865s (+13.7% 🔺) 11.021s (+5.8% 🔺) 0.156s 3 4.74x
🐘 Postgres Next.js (Turbopack) 11.642s (-7.0% 🟢) 12.358s (-2.6%) 0.715s 3 5.08x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.197s (-9.6% 🟢) 3.961s (-8.4% 🟢) 0.764s 8 1.00x
▲ Vercel Express 3.855s (+17.9% 🔺) 4.735s (+13.9% 🔺) 0.880s 7 1.21x
▲ Vercel Next.js (Turbopack) 3.867s (+10.6% 🔺) 4.487s (+5.4% 🔺) 0.620s 7 1.21x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 5.573s (-19.8% 🟢) 6.415s (-20.8% 🟢) 0.842s 5 1.00x
💻 Local Nitro 7.111s (-2.7%) 7.889s (-2.2%) 0.778s 4 1.28x
💻 Local Express 7.505s (~) 8.438s (-0.7%) 0.933s 4 1.35x
🐘 Postgres Express 49.315s (+9.3% 🔺) 50.147s (+10.6% 🔺) 0.832s 1 8.85x
🐘 Postgres Nitro 52.542s (+8.7% 🔺) 53.172s (+8.1% 🔺) 0.630s 1 9.43x
🐘 Postgres Next.js (Turbopack) 57.286s (+10.4% 🔺) 58.143s (+11.5% 🔺) 0.857s 1 10.28x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.560s (+32.0% 🔺) 5.288s (+30.4% 🔺) 0.728s 7 1.00x
▲ Vercel Next.js (Turbopack) 5.302s (+52.3% 🔺) 6.208s (+42.6% 🔺) 0.906s 5 1.16x
▲ Vercel Nitro 5.705s (+73.2% 🔺) 6.590s (+70.2% 🔺) 0.885s 6 1.25x

🔍 Observability: Express | Next.js (Turbopack) | Nitro

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 1.393s (-1.7%) 2.010s (~) 0.617s 15 1.00x
💻 Local Nitro 1.425s (-0.5%) 2.007s (~) 0.582s 15 1.02x
💻 Local Express 1.432s (-1.1%) 2.007s (~) 0.575s 15 1.03x
🐘 Postgres Next.js (Turbopack) 1.859s (-14.2% 🟢) 2.085s (-17.3% 🟢) 0.226s 15 1.33x
🐘 Postgres Express 1.959s (-6.2% 🟢) 2.476s (-5.0% 🟢) 0.518s 13 1.41x
🐘 Postgres Nitro 2.151s (+8.8% 🔺) 2.695s (+25.7% 🔺) 0.544s 12 1.54x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.829s (~) 3.637s (-4.1%) 0.808s 9 1.00x
▲ Vercel Nitro 2.830s (~) 3.702s (-1.7%) 0.872s 9 1.00x
▲ Vercel Next.js (Turbopack) 2.918s (~) 3.780s (~) 0.863s 8 1.03x

🔍 Observability: Express | Nitro | Next.js (Turbopack)

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 2.453s (-7.2% 🟢) 3.254s (+7.4% 🔺) 0.801s 10 1.00x
💻 Local Express 2.659s (-1.5%) 3.012s (~) 0.353s 10 1.08x
💻 Local Nitro 2.678s (-3.3%) 3.011s (~) 0.333s 10 1.09x
🐘 Postgres Express 11.178s (+2.5%) 11.692s (~) 0.514s 3 4.56x
🐘 Postgres Next.js (Turbopack) 11.590s (-8.6% 🟢) 12.362s (-7.6% 🟢) 0.771s 3 4.73x
🐘 Postgres Nitro 13.220s (+27.1% 🔺) 13.698s (+24.2% 🔺) 0.479s 3 5.39x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Next.js (Turbopack) 2.976s (-4.2%) 3.760s (-3.1%) 0.785s 9 1.00x
▲ Vercel Express 3.011s (-1.6%) 3.824s (+0.8%) 0.814s 8 1.01x
▲ Vercel Nitro 3.083s (~) 3.811s (-1.6%) 0.728s 8 1.04x

🔍 Observability: Next.js (Turbopack) | Express | Nitro

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 6.822s (-8.0% 🟢) 7.537s (-10.0% 🟢) 0.715s 5 1.00x
💻 Local Nitro 7.715s (~) 8.720s (~) 1.005s 4 1.13x
💻 Local Express 7.835s (-2.4%) 8.795s (-1.7%) 0.960s 4 1.15x
🐘 Postgres Express 51.962s (+8.9% 🔺) 52.328s (+8.4% 🔺) 0.366s 1 7.62x
🐘 Postgres Nitro 52.639s (+4.0%) 53.111s (+3.4%) 0.472s 1 7.72x
🐘 Postgres Next.js (Turbopack) 56.380s (-2.0%) 57.132s (-1.8%) 0.752s 1 8.26x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.445s (+6.8% 🔺) 4.213s (+8.9% 🔺) 0.768s 8 1.00x
▲ Vercel Next.js (Turbopack) 3.478s (-11.4% 🟢) 4.287s (-7.9% 🟢) 0.809s 7 1.01x
▲ Vercel Express 3.930s (+12.9% 🔺) 4.365s (+5.4% 🔺) 0.435s 7 1.14x

🔍 Observability: Nitro | Next.js (Turbopack) | Express

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 0.117s (-18.7% 🟢) 1.003s (~) 0.013s (-20.2% 🟢) 1.025s (~) 0.908s 10 1.00x
💻 Local Nitro 0.180s (-1.6%) 0.992s (~) 0.014s (-2.9%) 1.020s (~) 0.840s 10 1.54x
💻 Local Express 0.187s (~) 0.992s (~) 0.015s (-6.5% 🟢) 1.022s (~) 0.834s 10 1.60x
🐘 Postgres Next.js (Turbopack) 0.614s (-7.7% 🟢) 0.928s (-4.3%) 0.000s (+Infinity% 🔺) 1.016s (~) 0.402s 10 5.24x
🐘 Postgres Express 1.438s (-40.2% 🟢) 1.602s (-39.4% 🟢) 0.000s (+Infinity% 🔺) 2.013s (-33.3% 🟢) 0.575s 10 12.27x
🐘 Postgres Nitro 2.331s (+5.3% 🔺) 2.712s (-4.1%) 0.000s (~) 3.016s (~) 0.685s 10 19.89x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.890s (-6.3% 🟢) 3.228s (-6.3% 🟢) 0.149s (+8.6% 🔺) 3.892s (-5.7% 🟢) 1.003s 10 1.00x
▲ Vercel Express 2.986s (-3.8%) 3.238s (-2.2%) 0.182s (-4.5%) 3.887s (-3.4%) 0.901s 10 1.03x
▲ Vercel Next.js (Turbopack) 3.076s (-1.4%) 3.214s (-0.8%) 0.217s (+45.1% 🔺) 3.942s (+1.5%) 0.866s 10 1.06x

🔍 Observability: Nitro | Express | Next.js (Turbopack)

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Next.js (Turbopack) 12/12
🐘 Postgres Next.js (Turbopack) 7/12
▲ Vercel Express 5/12
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 💻 Local 10/12
Next.js (Turbopack) 💻 Local 10/12
Nitro 💻 Local 10/12
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Starter: Community world (local development)
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR consolidates all console logging calls in packages/core/src to use a structured logger utility built on the debug library with OpenTelemetry integration. This provides consistent, filterable logging and removes duplicate logging patterns.

Changes:

  • Replaced all console.log, console.warn, and console.error calls with structured loggers (runtimeLogger, stepLogger) that accept structured metadata
  • Removed duplicate logging where both eventsLogger and console.error were called for the same event
  • Updated test expectations to remove console spy mocking since logging is now handled by the structured logger

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/core/src/telemetry.ts Replaced console.warn with runtimeLogger.warn for OpenTelemetry unavailable warning
packages/core/src/serialization.ts Replaced console.error calls with runtimeLogger.error, adding structured metadata for serialization failures
packages/core/src/runtime/suspension-handler.ts Replaced console.warn calls with runtimeLogger.warn, adding structured context including workflowRunId and correlationId
packages/core/src/runtime/step-handler.ts Replaced console.error/warn calls with stepLogger equivalents, converting formatted error stack strings to structured metadata
packages/core/src/runtime.ts Replaced console.warn/error calls with runtimeLogger equivalents, adding structured metadata for workflow status and errors
packages/core/src/observability.ts Replaced console.error with runtimeLogger.error for event data hydration errors
packages/core/src/events-consumer.ts Removed duplicate console.error call, keeping only eventsLogger.error for callback errors
packages/core/src/events-consumer.test.ts Removed console.error spy test code that is no longer needed since duplicate logging was removed

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Logger now outputs error/warn to console (always visible, not just when DEBUG enabled)
- Downgrade warn → info for expected states (OTel unavailable, workflow/step already completed, idempotency cases)
- Downgrade error → warn for transient failures (step invoked erroneously, error with retry pending)
- Remove verbose debug logs from hot paths (events-consumer)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Member

@VaguelySerious VaguelySerious left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I also would love if the logger eventually moved to utils and then cli could use it too, among other packages, so that we eventually have a unified way of setting debug log level

Copy link
Collaborator

@karthikscale3 karthikscale3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested and looks good

@pranaygp pranaygp merged commit e0061b8 into main Feb 5, 2026
98 checks passed
@pranaygp pranaygp deleted the pranaygp/improved-logging branch February 5, 2026 00:16
pranaygp added a commit that referenced this pull request Feb 5, 2026
…-parallelization

* origin/main:
  Add x-workflow-run-id header to queue messages (#922)
  Bump Next.js and React in workbenches (#944)
  Add subpath export resolution for package IDs (#901)
  Consolidate console logging to structured logger utility (#935)

# Conflicts:
#	packages/core/src/runtime/step-handler.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants