[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e 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

[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

, '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

[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

, '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 \u003e 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

[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

, '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

[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

, '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

[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

, '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

[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

, '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

[Nuxt] Ability to customize/turn off Sentry's Nitro hook handler #15409

Description

@brtinney

Problem Statement

I want to be able to control the contexts that are being attached to the error (in particular, things about the request), but since there's no way to customize the handler that Sentry adds to hook into the nitro error event, I'm left in a bind. In particular, this causes me two issues:

  1. I cannot control the automatic filtering applied in the provided handler to exclude 4xx errors
  2. I cannot attach context from Nitro to the Sentry context -- doing this in beforeSend is not possible because even with the experimental asyncContext via useEvent(), the context will not be available in the sentry.server.config.ts file. However, it is fully available in the handler for the error hook.

Attempting to solely add a second handler that does everything I want runs into the issue of 5xx errors being captured by the Sentry handler, and my handler can't submit the error with the better context, as it gets dropped as a duplicate (not that receiving two errors is great, either).

Solution Brainstorm

I think there are some straightforward solutions, any of which I could make work to cover both of my concerns above:

  1. Add a property to the Nuxt module config that takes a function that will be used in place of the "default" Sentry-provided error hook handler
  2. Add a hook that we can use to modify the Sentry context, etc. before the rest of the hook handler runs. For example:
importtype{CapturedErrorContext}from'nitropack/runtime/types'typeHookResult=void|Promise<void>exportdefaultdefineNitroPlugin((nitroApp)=>{nitroApp.hooks.hook('error',(error,context)=>{nitroApp.hooks.callHook('sentry:error',error,context)// ...})})declare module 'nitropack'{interfaceNitroRuntimeHooks{'sentry:error': (error: Error,context: CapturedErrorContext)=>HookResult}}
  1. Add a flag to disable the included hook and leave it up to us to handle it (but keep the custom proxy handler, etc.)

The first or third solution is the most straightforward for me to get what I want -- I already have my own hook that does what I want. The second one has some downsides in that you can't actually drop the error via the custom hook, which is probably not great DX.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions