feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(node): Add instrumentation for hono handler - #17428

Merged
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler
Sep 23, 2025
Merged

feat(node): Add instrumentation for hono handler#17428
s1gr1d merged 11 commits into
getsentry:developfrom
Karibash:feature/hono-instrumentation-handler

Conversation

@Karibash

@KaribashKaribash commented Aug 18, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR enhances the Hono integration by adding comprehensive handler instrumentation, error handling capabilities, and thorough test coverage. The changes build upon the basic Hono integration to provide a complete tracing and error monitoring solution.

New Features

  • Handler Instrumentation: Added instrumentation for Hono handlers and middleware, providing detailed tracing capabilities
  • Error Handler: Implemented setupHonoErrorHandler() function to capture and report errors to Sentry with configurable error filtering
  • Public API: Added Hono integration to the main package exports, making it available as @sentry/node
  • Tracing Module: Included Hono integration in the tracing integrations index

Bug Fixes

  • CJS Compatibility: Fixed an issue where applying patches failed in CommonJS environments
  • Type Corrections: Fixed incorrect MiddlewareHandler type definition to ensure proper TypeScript support

Implementation Details

  • Instrumentation: Created HonoInstrumentation class that wraps Hono middleware handlers via class extension instead of function replacement for better compatibility
  • Type Definitions: Added comprehensive TypeScript type definitions vendored from Hono's official types
  • Constants: Defined Hono-specific attribute names for OpenTelemetry integration
  • CJS Compatibility: Fixed patching issues in CommonJS environments

Testing

  • Integration Tests: Added comprehensive test suite covering:
    • ESM and CJS compatibility
    • Multiple HTTP methods (GET, POST, PUT, DELETE, PATCH)
    • Various route patterns (sync/async, different paths)
    • Middleware and handler instrumentation verification
    • Error handling scenarios
    • Span attribute validation

Related Issue

close#15260

cursor[bot]

This comment was marked as outdated.

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 32e3a23 to 505c480CompareAugust 18, 2025 02:31
cursor[bot]

This comment was marked as outdated.

@s1gr1ds1gr1d assigned s1gr1d and unassigned s1gr1dAug 25, 2025
@s1gr1d
s1gr1d requested review from Lms24 and s1gr1dAugust 25, 2025 11:06
@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 505c480 to a7ef204CompareAugust 25, 2025 11:22
@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d@Lms24
Hi, just wanted to kindly follow up on this PR.
Is there anything I can do to help move it forward, or any feedback you’d like me to address?

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for your contribution 🙌
I just have some suggestions and follow-up questions.

And sorry for the long wait, we had some busy weeks and I try to look at your PR sooner next time :)

}

const path = c.req.path;
const spanName = `${type.replace('_', ' ')} - ${path}`;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What would be an example span name here? I think there are no tests that check this name so I couldn't find an example.

Would be good to also have tests for this.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I checked other test codes, but I couldn’t find a way to test the span name.
I also looked into transaction.spans, but it doesn’t seem to include the span name.

{
"span_id": "c6b2cd926a07da13",
"trace_id": "8d75c4926828d1b7b98dc2b9356c3fc9",
"data": {
"sentry.origin": "auto.http.otel.hono",
"sentry.op": "request_handler.hono",
"hono.type": "request_handler",
"hono.name": "/async"
},
"description": "/async",
"parent_span_id": "b3270618aac86a93",
"start_timestamp": 1757852841.829,
"timestamp": 1757852841.8291407,
"status": "ok",
"op": "request_handler.hono",
"origin": "auto.http.otel.hono"
}

Do you know how we can test the span name in this case?

if (
result &&
typeof result === 'object' &&
typeof Object.getOwnPropertyDescriptor(result, 'then')?.value === 'function'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can use isThenable here from @sentry/core

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Thanks, I’ve fixed this in the following commit: 8dc3939

* Safely executes a function and handles errors.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _safeExecute(execute: () => any, onSuccess: () => void, onFailure: (error: unknown) => void): () => any {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm wondering if it would be possible to type this instead of relying on any here?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Since the return value of handler.apply(this, [c, next]) is any, I think it would be difficult to type this explicitly.

path,
...handlers.map((handler, index) =>
instrumentation._wrapHandler(
index + 1 === handlers.length ? HonoTypes.REQUEST_HANDLER : HonoTypes.MIDDLEWARE,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we be sure that the handlers are always those two in this order?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I overlooked the case where the middleware is registered on its own.
That has been fixed in the following commit: 7172211

@s1gr1d

Copy link
Copy Markdown
Member

@Karibash just a general heads-up: It's awesome that you are working on this instrumentation right now. Keep in mind that we are planning to start working on a dedicated hono SDK in about a month. So your integration can be used in the meantime but we might need to deprecate it once the new SDK is stable :)

@Karibash

Copy link
Copy Markdown
ContributorAuthor

@s1gr1d Thanks for the heads-up!
Just to clarify — will the upcoming SDK take a different approach than using @opentelemetry/instrumentation?
I’m also curious to hear a bit more about what approach you’re planning to take for the new implementation.

@s1gr1d

Copy link
Copy Markdown
Member

It will use OTel under the hood but we'll focus on making it work on Cloudflare as a first priority.

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Got it — so in that sense, the approach in this PR won’t differ too much from what you’re planning for the new SDK (aside from the implementation details that will naturally evolve), right?

@s1gr1d

Copy link
Copy Markdown
Member

Probably not, but it's not planned out in detail yet

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from a7ef204 to bafc2beCompareSeptember 13, 2025 09:22
cursor[bot]

This comment was marked as outdated.

@s1gr1d

Copy link
Copy Markdown
Member

Can you check the missing exports?
https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Can you check the missing exports? https://github.com/getsentry/sentry-javascript/actions/runs/17712340530/job/50332837288?pr=17428#step:16:41

I’ve fixed this in the following commit: 20f5ac8

@Karibash

Copy link
Copy Markdown
ContributorAuthor

Hi @s1gr1d, any updates on this PR?

"express": "^4.21.1",
"generic-pool": "^3.9.0",
"graphql": "^16.3.0",
"hono": "^4.8.12",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you update the version here? It's popping up in our vulnerability check.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

fixed it
dbb1413

@Karibash
Karibashforce-pushed the feature/hono-instrumentation-handler branch from 20f5ac8 to 3c89525CompareSeptember 23, 2025 08:37

@s1gr1ds1gr1d left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for contributing this!

@s1gr1ds1gr1d changed the title feature(node): Add instrumentation to the handler in Honofeat(node): Add instrumentation for hono handlerSep 23, 2025
@s1gr1d
s1gr1d merged commit 01fa69d into getsentry:developSep 23, 2025
167 checks passed
andreiborza pushed a commit that referenced this pull request Sep 23, 2025
This PR adds the external contributor to the CHANGELOG.md file, so that
they are credited for their contribution. See #17428
Co-authored-by: s1gr1d <32902192+s1gr1d@users.noreply.github.com>
@Karibash
Karibash deleted the feature/hono-instrumentation-handler branch September 24, 2025 00:03
@github-actionsgithub-actionsBot mentioned this pull request Sep 24, 2025
Sign up for freeto 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.

Implement Hono SDK

2 participants

@Karibash@s1gr1d