Skip to content

feat(hono): Instrument middlewares app.use()#19611

Merged
s1gr1d merged 12 commits intodevelopfrom
sig/hono-middleware
Mar 4, 2026
Merged

feat(hono): Instrument middlewares app.use()#19611
s1gr1d merged 12 commits intodevelopfrom
sig/hono-middleware

Conversation

@s1gr1d
Copy link
Member

@s1gr1d s1gr1d commented Mar 3, 2026

Middleware spans are named either after the function name or they are numbered.

Middleware in Hono is onion-shaped (see docs) and technically, this shape would create a nested children-based span structure. This however, is not as intuitive and so I decided (after also talking to @andreiborza and @JPeer264) to create a sibiling-like structure:

image

Closes #19585


expect(fakeApp._capturedThis).toBe(fakeApp);
});
});
Copy link

Choose a reason for hiding this comment

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

Missing integration or E2E test for feat PR

Medium Severity

This feat PR introduces middleware span instrumentation but only includes unit tests (patchAppUse.test.ts). No integration or E2E test is added to verify that middleware spans actually appear in transaction payloads sent to Sentry. The existing integration test suite in dev-packages/cloudflare-integration-tests/suites/hono-sdk/ does not include any assertions about middleware spans (e.g., spans with op: 'middleware.hono' in the transaction's span list). An integration or E2E test covering the new behavior is recommended.

Additional Locations (1)

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.63 kB - -
@sentry/browser - with treeshaking flags 24.13 kB - -
@sentry/browser (incl. Tracing) 42.43 kB - -
@sentry/browser (incl. Tracing, Profiling) 47.09 kB - -
@sentry/browser (incl. Tracing, Replay) 81.25 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 70.87 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 85.95 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 98.21 kB - -
@sentry/browser (incl. Feedback) 42.44 kB - -
@sentry/browser (incl. sendFeedback) 30.3 kB - -
@sentry/browser (incl. FeedbackAsync) 35.35 kB - -
@sentry/browser (incl. Metrics) 26.8 kB - -
@sentry/browser (incl. Logs) 26.94 kB - -
@sentry/browser (incl. Metrics & Logs) 27.61 kB - -
@sentry/react 27.38 kB - -
@sentry/react (incl. Tracing) 44.77 kB - -
@sentry/vue 30.08 kB - -
@sentry/vue (incl. Tracing) 44.3 kB - -
@sentry/svelte 25.66 kB - -
CDN Bundle 28.17 kB - -
CDN Bundle (incl. Tracing) 43.26 kB - -
CDN Bundle (incl. Logs, Metrics) 29.01 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 44.1 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 68.09 kB - -
CDN Bundle (incl. Tracing, Replay) 80.14 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 81 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 85.65 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 86.53 kB - -
CDN Bundle - uncompressed 82.35 kB - -
CDN Bundle (incl. Tracing) - uncompressed 128.07 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 85.19 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 130.9 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 208.85 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 244.95 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 247.77 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 257.86 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 260.67 kB - -
@sentry/nextjs (client) 47.18 kB - -
@sentry/sveltekit (client) 42.89 kB - -
@sentry/node-core 52.25 kB +0.02% +8 B 🔺
@sentry/node 174.71 kB +0.01% +4 B 🔺
@sentry/node - without tracing 97.4 kB +0.02% +11 B 🔺
@sentry/aws-serverless 113.2 kB +0.01% +8 B 🔺

View base workflow run

Copy link
Member

@logaretm logaretm left a comment

Choose a reason for hiding this comment

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

+1 for peeling the onion, I did the same in Nitro's SDK for h3 instrumentation.

I got a question tho, based on the screenshot doesn't this show the spans executing in parallel rather than in serial?

Base automatically changed from sig/hono-parametrized-errors to develop March 4, 2026 09:44
# Conflicts:
#	packages/hono/src/cloudflare/middleware.ts
#	packages/hono/test/cloudflare/middleware.test.ts
@s1gr1d
Copy link
Member Author

s1gr1d commented Mar 4, 2026

Regarding your question: It just looks parallel, as all the middlewares had the artificial timeout only before calling next(). If I add another timeout after next() (e.g. inside middlewareA) it looks like this:

image

const MIDDLEWARE_ORIGIN = 'auto.middleware.hono';

// Module-level counter for anonymous middleware span names
let MIDDLEWARE_IDX = 0;
Copy link
Member

Choose a reason for hiding this comment

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

l/q: In Cloudflare one isolate could handle more requests. Currently I am not 100% sure every if every request has their own bundled code (ergo starting at 0). Have you tried it out on Cloudflare how it is behaving under load when deployed?

Copy link
Member Author

Choose a reason for hiding this comment

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

I tested it and it always starts at 0 👍

However, I'm changing it a bit to only increment if we apply the anonymous name. Right now, it increments on every middleware call which results in counting from 0 to 2 e.g. in this case, where timeout2 is in-between:

image

Copy link
Member Author

Choose a reason for hiding this comment

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

I actually removed the numbering again. OTel also just uses <anonymous> as a name for anonymous functions and using a numbering here was just a best-effort to better distinguish them. But as it creates potentially wrong data, it's probably better if people just name their middleware (and most often, it's actually named).

Copy link
Member

Choose a reason for hiding this comment

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

Cool. I like that better

@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 9,197 - 9,286 -1%
GET With Sentry 1,727 19% 1,708 +1%
GET With Sentry (error only) 6,223 68% 6,093 +2%
POST Baseline 1,209 - 1,183 +2%
POST With Sentry 594 49% 589 +1%
POST With Sentry (error only) 1,069 88% 1,055 +1%
MYSQL Baseline 3,306 - 3,308 -0%
MYSQL With Sentry 412 12% 467 -12%
MYSQL With Sentry (error only) 2,698 82% 2,711 -0%

View base workflow run

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

@s1gr1d s1gr1d enabled auto-merge (squash) March 4, 2026 14:02
@s1gr1d s1gr1d merged commit 685cf5c into develop Mar 4, 2026
224 checks passed
@s1gr1d s1gr1d deleted the sig/hono-middleware branch March 4, 2026 14:21
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.

[Hono] Record middleware spans

3 participants