内容源于:https://docs.sentry.io/platforms/javascript/guides/vue/
系列
1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source MapsSentry For React 完整接入详解脑图
公众号:黑客下午茶
快速开始
Sentry
的SDK
支持自动报告错误和异常。
安装
Sentry
通过在应用程序runtime
使用SDK
捕获数据。
# 使用 npmnpm install --save @sentry/vue @sentry/tracing# 使用 yarnyarn add @sentry/vue @sentry/tracing
配置
配置应该在应用程序的生命周期中尽早进行。
要在您的Vue
应用程序中初始化Sentry
,请将其添加到您的app.js
中:
Vue2
import Vue from "vue";import Router from "vue-router";import * as Sentry from "@sentry/vue";import { Integrations } from "@sentry/tracing";Vue.use(Router);const router = new Router({// ...});Sentry.init({Vue,dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new Integrations.BrowserTracing({routingInstrumentation: Sentry.vueRouterInstrumentation(router),tracingOrigins: ["localhost", "my-site-", /^\//],}),],// Set tracesSampleRate to 1.0 to capture 100%// of transactions for performance monitoring.// We recommend adjusting this value in productiontracesSampleRate: 1.0,});// ...new Vue({router,render: h => h(App),}).$mount("#app");
Vue3
import { createApp } from "vue";import { createRouter } from "vue-router";import * as Sentry from "@sentry/vue";import { Integrations } from "@sentry/tracing";const app = createApp({// ...});const router = createRouter({// ...});Sentry.init({app,dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new Integrations.BrowserTracing({routingInstrumentation: Sentry.vueRouterInstrumentation(router),tracingOrigins: ["localhost", "my-site-", /^\//],}),],// Set tracesSampleRate to 1.0 to capture 100%// of transactions for performance monitoring.// We recommend adjusting this value in productiontracesSampleRate: 1.0,});app.use(router);app.mount("#app");
此外,Vue 3
允许您使用具有相同Sentry SDK
实例的多个应用程序,以及在SDK
已经初始化后动态添加更多应用程序。
Vue 3 - 多个 App
const appOne = Vue.createApp(App);const appTwo = Vue.createApp(App);const appThree = Vue.createApp(App);Sentry.init({app: [appOne, appTwo, appThree],});
Vue 3 - 手动初始化
import * as Sentry from "@sentry/vue";// ...const app = createApp(App);Sentry.init({app,// ...});const miscApp = createApp(MiscApp);miscApp.mixin(Sentry.createTracingMixins({ trackComponents: true }));Sentry.attachErrorHandler(miscApp, { logErrors: true });
SDK
接受一些不同的配置选项,可让您更改其行为:
attachProps
(默认为true
)- 包括所有Vue
组件的带有事件的属性(props
)。logErrors
(默认为false
) - 决定SDK
是否也应该调用Vue
的原始logError
函数。trackComponents
(默认为false
)- 决定是否通过hooking
到其生命周期方法来跟踪组件。可以设置为布尔值(boolean
),以启用/禁用对所有组件的跟踪,或设置为特定组件名称的数组(区分大小写)。timeout
(默认为2000
)- 以毫秒为单位的时间,指示等待被跟踪的根活动标记为完成(finished
)并发送给Sentry
的时间。hooks
(默认为['activate', 'mount', 'update'
])- 在组件生命周期'activate' | 'create' | 'destroy' | 'mount' | 'unmount' | 'update'
期间要跟踪的hooks
列表。
如果启用
SDK
,Vue
将不会在内部调用其logError
。因此,Vue
渲染器中发生的错误将不会显示在开发人员控制台中。要保留此功能,请传递logErrors:true
选项。
验证
此代码段包含一个故意错误,因此您可以在设置后立即测试一切是否正常:
向页面添加一个引发错误的按钮:
// ...<button @click="throwError">Throw error</button>// ...export default {// ...methods: {throwError() {throw new Error('Sentry Error');}}};
配置
基本选项
SDK
可以使用多种选项进行配置。这些选项在SDK
中基本上是标准化的,但在更好地适应平台特性方面存在一些差异。选项是在SDK
首次初始化时设置的。
选项作为对象传递给init()
函数:
Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",maxBreadcrumbs: 50,debug: true,});
常见选项
跨SDK
的常用选项列表。这些在所有SDK
中的工作方式或多或少都相同,但为了更好地支持平台,将存在一些细微差别。 可以从环境变量(SENTRY_DSN
、SENTRY_ENVIRONMENT
、SENTRY_RELEASE
)中读取的选项会自动读取。
dsn
DSN
告诉SDK
将事件发送到哪里。如果没有提供这个值,SDK
将尝试从SENTRY_DSN
环境变量中读取它。如果这个变量也不存在,SDK
就不会发送任何事件。
在没有进程环境(如浏览器)的运行时中,fallback
不会应用。
更多:https://docs.sentry.io/product/sentry-basics/dsn-explainer/#dsn-utilization
debug
打开或关闭调试模式。如果启用了调试,如果发送事件时出现问题,SDK
将尝试打印出有用的调试信息。默认值总是false
。一般不建议在生产环境中打开它,尽管打开debug
模式不会引起任何安全问题。
release
设置 release。某些SDK
会尝试自动配置release
,但是最好手动设置release
,以确保该release
与您的deploy integrations
或source map uploads
同步。Release
名称是字符串,但是Sentry
会检测到某些格式,并且它们的呈现方式可能有所不同。
更多:https://docs.sentry.io/product/releases/
默认情况下,SDK
会尝试从环境变量SENTRY_RELEASE
中读取该值(在浏览器SDK
中,将从window.SENTRY_RELEASE
中读取该值,如果可用)。
environment
设置环境。此字符串为自由形式,默认情况下不设置。一个release
可以与多个环境相关联,以便在 UI 中将它们分开(可以考虑staging
与prod
或类似的方式)。
默认情况下,SDK
将尝试从SENTRY_ENVIRONMENT
环境变量中读取该值(浏览器SDK
除外)。
tunnel
设置将用于传输捕获事件的URL
,而不是使用DSN
。这可用于解决广告拦截器(ad-blockers
)或对发送到Sentry
的事件进行更精细的控制。此选项需要实现自定义服务器端点。
更多:https://docs.sentry.io/platforms/javascript/troubleshooting/#dealing-with-ad-blockers
sampleRate
配置错误事件的采样率,范围为0.0
到1.0
。默认值为1.0
,表示发送了100%
的错误事件。如果设置为0.1
,则仅发送10%
的错误事件。事件是随机选择的。
maxBreadcrumbs
这个变量控制应该捕获的面包屑总数。默认值为100
。
attachStacktrace
当启用时,堆栈跟踪将自动附加到所有记录的消息。堆栈跟踪总是附加到异常;然而,当设置此选项时,堆栈跟踪也会与消息一起发送。例如,该选项意味着堆栈跟踪显示在所有日志消息的旁边。
该选项默认为off
。
Sentry
中的分组对于有和没有堆栈跟踪的事件是不同的。因此,当您为某些事件启用或禁用此flag
时,您将获得新组。
denyUrls
与不应该发送到Sentry
的错误URL
相匹配的字符串或正则表达式模式列表。默认情况下,将发送所有错误。这是一个 “contains(包含)” 匹配整个文件 URL。因此,如果你添加,它也会匹配
/myfile/
。默认情况下,将发送所有错误。
allowUrls
匹配错误URL
的字符串列表或正则表达式模式的遗留别名,这些错误URL
应该专门发送给Sentry
。默认情况下,将发送所有错误。这是一个 “contains(包含)” 匹配整个文件 URL。因此,如果您将添加到它,它也将匹配
/myfile/
。默认情况下,所有错误将被发送。
autoSessionTracking
设置为true
时,SDK
将向Sentry
发送session
事件。这在所有浏览器SDK
中都受支持,每个页面加载和页面导航都向Sentry
发出一个session
。在移动SDK
中,当应用进入后台超过30
秒时,会话结束。
initialScope
要设置为初始作用域的数据。初始作用域可以定义为对象或回调函数,如下所示。
对象:
Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",debug: true,initialScope: {tags: {"my-tag": "my value"},user: {id: 42, email: "john.doe@"},}});
回调函数:
Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",debug: true,initialScope: scope => {scope.setTags({ a: 'b' });return scope;},});
maxValueLength
单个值在被截断之前可以具有的最大字符数(默认为250
)。
normalizeDepth
Sentry SDK
将任何上下文数据标准化到给定的深度。 任何包含结构比这更深的数据的key
都将使用其类型([Object]
或[Array]
)进行修剪和标记,而不会进一步遍历树。默认情况下,步行执行3
级深度。
集成配置
对于许多平台,SDK 集成可以与之一起配置。在一些平台上,这是init()
调用的一部分,而在另一些平台上,则应用不同的模式。
integrations
在某些 SDK 中,在库初始化时通过此参数配置集成。
更多:
defaultIntegrations
这可以用来禁用默认添加的集成。当设置为false
时,不会添加默认的集成。
Hooks
这些选项可用于以各种方式 hookSDK
,以定制事件的报告。
beforeSend
使用SDK-specific
事件对象调用此函数,可以返回修改后的事件对象或不返回任何内容,以跳过报告事件。例如,这可以用于在发送前手动剥离PII
。
beforeBreadcrumb
在将面包屑添加到作用域之前,使用SDK
特定的面包屑(SDK-specific breadcrumb
)对象调用此函数。当该函数未返回任何内容时,将删除breadcrumb
。要传递breadcrumb
,请返回第一个参数,其中包含breadcrumb
对象。回调通常会获得第二个参数(称为“hint”
),该参数包含创建breadcrumb
的原始对象,以进一步自定义面包屑的外观。
传输选项
Transports
被用来发送事件到Sentry
。可以在某种程度上对传输进行定制,以更好地支持高度特定的部署。
transport
切换出用于发送事件的transport
。如何运作取决于SDK
。例如,它可以用于捕获事件以进行单元测试,或通过需要代理身份验证的更复杂的设置发送事件。
跟踪选项
tracesSampleRate
0
到1
之间的数字,控制给定事务发送到Sentry
的概率百分比。(0
表示0%
,1
表示100%
)同样适用于应用程序中创建的所有事务。必须定义这个或tracesSampler
以启用跟踪。
tracesSampler
一个函数负责确定一个给定的事务将被发送到Sentry
的概率百分比。它将自动被传递有关事务和创建它的上下文的信息,并且必须返回一个介于0
(被发送的概率为0%
)和1
(被发送的概率为100%
) 之间的数字。还可以用于过滤事务,对不需要的事务返回0
。必须定义这个或tracesSampleRate
来启用跟踪。
集成
默认集成
Sentry
的所有SDK
都提供集成,可扩展SDK
的功能。
默认情况下启用系统集成以集成到标准库或解释器本身。 它们被记录在案,因此您既可以了解它们的作用,也可以在它们引起问题时禁用它们。
默认启用
InboundFilters
Import name:Sentry.Integrations.InboundFilters
通过这种集成,您可以根据给定异常中的类型,消息或 URL 忽略特定错误。
默认情况下,它忽略以Script error
或Javascript error: Script error
开头的错误。
要配置这个集成,直接使用ignoreErrors
,denyUrls
,和allowUrls
SDK 选项。请记住,denyURL
和allowURL
只对捕获的异常有效,而不是原始消息事件。
FunctionToString
Import name:Sentry.Integrations.FunctionToString
这种集成使SDK
可以提供原始的函数和方法名称,即使我们的错误(error
)或面包屑处理程序(breadcrumbs handlers
)包装了它们也是如此。
TryCatch
Import name:Sentry.Integrations.TryCatch
这个集成封装了原生time
和events APIs
(setTimeout
,setInterval
,requestAnimationFrame
,addEventListener/removeEventListener
) 在try/catch
块处理async
异常。
Breadcrumbs
Import name:Sentry.Integrations.Breadcrumbs
这种集成封装了原生 API 以捕获面包屑。默认情况下,Sentry SDK
封装了所有API
。
可用选项:
{// 记录对 `console.log`、`console.debug` 等的调用console: boolean;// 记录所有点击和按键事件// - 当提供带有 `serializeAttribute` key 的对象时,// 面包屑集成将在 DOM 元素中查找给定的属性,同时生成面包屑路径。// 匹配的元素后跟它们的自定义属性,而不是它们的 `id` 或 `class` 名称。dom: boolean | { serializeAttribute: string | string[] };// 记录使用 `Fetch API` 完成的 `HTTP` 请求fetch: boolean;// 记录对 `history.pushState` 的调用history: boolean;// 每当我们向服务器发送事件时记录sentry: boolean;// 记录使用 XHR API 完成的 HTTP 请求xhr: boolean;}
GlobalHandlers
Import name:Sentry.Integrations.GlobalHandlers
这个集成附加了全局处理程序来捕获未捕获的exceptions
和未处理的rejections
。
可用的选项:
{onerror: boolean;onunhandledrejection: boolean;}
LinkedErrors
Import name:Sentry.Integrations.LinkedErrors
此集成允许您配置linked
错误。它们将被递归地读取到指定的限制,并由特定的key
执行查找。默认情况下,Sentry SDK
将限制设置为5
,使用的键key
是cause
。
可用的选项:
{key: string;limit: number;}
这是如何实现的代码示例:
document.querySelector("#get-reviews-btn").addEventListener("click", async event => {const movie = event.target.dataset.title;try {const reviews = await fetchMovieReviews(movie);renderMovieReviews(reviews);} catch (e) {const fetchError = new Error(`Failed to fetch reviews for: ${movie}`);fetchError.cause = e;Sentry.captureException(fetchError);renderMovieReviewsError(fetchError);}});
UserAgent
Import name:Sentry.Integrations.UserAgent
这种集成将user-agent
信息附加到事件中,这使我们能够正确地分类并使用特定的操作系统(OS
),浏览器(browser
)和版本(version
)信息对其进行标记。
Dedupe
Import name:Sentry.Integrations.Dedupe
这种集成消除了某些事件的重复数据。如果您收到许多重复的错误,这会很有帮助。请注意,Sentry
只会比较堆栈跟踪(stack traces
)和指纹(fingerprints
)。默认情况下为浏览器启用此集成。
import * as Sentry from "@sentry/browser";import { Dedupe as DedupeIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new DedupeIntegration()],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/dedupe.min.js"integrity="sha384-3IMGY+DN27Yns7KDiKL3sOWXBYlILQ/bxLogt02NG7DL7qEJHIMbpnXfqNlO0J8G"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new Dedupe()],});
修改系统集成
要禁用系统集成,请在调用init()
时设置defaultIntegrations: false
。
要覆盖它们的设置,请提供一个带有您的配置到集成选项的新实例。 例如,要关闭浏览器捕获控制台调用:integrations: [new Sentry.Integrations.Breadcrumbs({ console: false })]
。
删除集成
此示例删除了用于向事件添加面包屑的默认启用集成:
Sentry.init({// ...integrations: function(integrations) {// integrations will be all default integrationsreturn integrations.filter(function(integration) {return integration.name !== "Breadcrumbs";});},});
可插拔集成
这些可插拔的集成是为特定的应用程序和/或框架增加功能的代码片段。我们对它们进行了记录,这样您就可以看到它们的功能,并且可以启用它们。
如何启用
安装@sentry/integrations
包,并提供一个带有你配置到integrations
选项的新实例。加载SDK
之后,包括插件。
示例:
import * as Sentry from "@sentry/browser";import { ReportingObserver as ReportingObserverIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new ReportingObserverIntegration()],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/reportingobserver.min.js"integrity="sha384-20D83MPBNSRANJFguhj0o9Qo7p9MCemwdMMQXotwA8742WuIwga85k+T7qEgIMWK"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new ReportingObserver()],});
ExtraErrorData
Import name:Sentry.Integrations.ExtraErrorData
这个集成从错误对象中提取所有非原生(non-native)属性,并将它们作为extra
数据附加到事件中。
可用的选项:
import * as Sentry from "@sentry/browser";import { ExtraErrorData as ExtraErrorDataIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new ExtraErrorDataIntegration({// limit of how deep the object serializer should go. Anything deeper than limit will// be replaced with standard Node.js REPL notation of [Object], [Array], [Function] or// a primitive value. Defaults to 3.depth: number;})],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/extraerrordata.min.js"integrity="sha384-DMO/ZWwA4ztkOtskx1Uad3cH6lbfSA/PGdW2IZ7A/c2qd/BU6zh5xiJ5D4nxJbye"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new ExtraErrorData({// limit of how deep the object serializer should go. Anything deeper than limit will// be replaced with standard Node.js REPL notation of [Object], [Array], [Function] or// a primitive value. Defaults to 3.depth: number;})],});
CaptureConsole
Import name:Sentry.Integrations.CaptureConsole
这种集成捕获所有的Console API
调用,并使用captureMessage
调用将它们重定向到Sentry
。然后,它会重新触发以保留默认的原生行为。
import * as Sentry from "@sentry/browser";import { CaptureConsole as CaptureConsoleIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new CaptureConsoleIntegration({// array of methods that should be captured// defaults to ['log', 'info', 'warn', 'error', 'debug', 'assert']levels: string[];})],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/captureconsole.min.js"integrity="sha384-FJ5n80A08NroQF9DJzikUUhiCaQT2rTIYeJyHytczDDbIiejfcCzBR5lQK4AnmVt"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new CaptureConsole({// array of methods that should be captured// defaults to ['log', 'info', 'warn', 'error', 'debug', 'assert']levels: string[];})],});
Debug
Import name:Sentry.Integrations.Debug
通过这种集成,您可以检查已处理事件的内容,该事件将被传递到beforeSend
并有效地发送到Sentry SDK
。无论何时注册,它都将始终作为最后的集成运行。
可用的选项:
import * as Sentry from "@sentry/browser";import { Debug as DebugIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new DebugIntegration({// trigger DevTools debugger instead of using console.logdebugger: boolean;// stringify event before passing it to console.logstringify: boolean;})],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/debug.min.js"integrity="sha384-OIzIETBTnmaXcnCVlI4DzHq1+YxDdBS6uyZPp8yS60YZNUqzIQvrudJplBqEZ09K"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new Debug({// trigger DevTools debugger instead of using console.logdebugger: boolean;// stringify event before passing it to console.logstringify: boolean;})],});
Offline
Import name:Sentry.Integrations.Offline
此集成使用Web
浏览器的在线和离线事件
来检测何时没有可用的网络连接。如果离线,它会将事件保存到Web
浏览器的客户端存储(通常是IndexedDB
),然后在网络连接恢复时自动上传事件。
Online and offline events
/en-US/docs/Web/API/Navigator/Online_and_offline_events
此插件不会尝试为其他场景提供本地存储或重试。 例如,如果浏览器有本地连接但没有互联网连接,那么它可能会报告它在线,并且在这种情况下,Sentry
的Offline
插件不会尝试保存或重试任何发送失败。
import * as Sentry from "@sentry/browser";import { Offline as OfflineIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new OfflineIntegration({// limit how many events will be localled saved. Defaults to 30.maxStoredEvents: number;})],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/offline.min.js"integrity="sha384-rRq5WRQ3OncIj4lduaVZMtyfVwZnqeWXM0nXyXckOrhFLS2mlKEYX+VAlbLlIZL4"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new Offline({// limit how many events will be localled saved. Defaults to 30.maxStoredEvents: number;})],});
RewriteFrames
Import name: Sentry.Integrations.RewriteFrames
这种集成允许您对堆栈跟踪的每个帧应用转换。 在流线型(streamlined
)场景中,它可用于更改其来源的文件帧的名称,或者可以使用迭代函数为其提供任意变换。
在Windows
机器上,您必须使用Unix
路径并跳过root
选项中的卷号才能启用。例如C:\\Program Files\\Apache\\www
将不起作用,但是/Program Files/Apache/www
将起作用。
可用的选项:
import * as Sentry from "@sentry/browser";import { RewriteFrames as RewriteFramesIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new RewriteFramesIntegration({// root path that will be stripped from the current frame's filename by the default iteratee if the filename is an absolute pathroot: string;// a custom prefix that will be used by the default iteratee (default: `app://`)prefix: string;// function that takes the frame, applies a transformation, and returns ititeratee: (frame) => frame;})],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/rewriteframes.min.js"integrity="sha384-WOm9k3kzVt1COFAB/zCXOFx4lDMtJh/2vmEizIwgog7OW0P/dPwl3s8f6MdwrD7q"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new RewriteFrames({// root path that will be stripped from the current frame's filename by the default iteratee if the filename is an absolute pathroot: string;// a custom prefix that will be used by the default iteratee (default: `app://`)prefix: string;// function that takes the frame, applies a transformation, and returns ititeratee: (frame) => frame;})],});
使用示例:
例如,如果文件的完整路径是/www/src/app/file.js
:
ReportingObserver
Import name: Sentry.Integrations.ReportingObserver
此集成挂钩到ReportingObserver API
并将捕获的事件发送到Sentry
。它可以配置为仅处理特定的issue
类型。
可用的选项:
import * as Sentry from "@sentry/browser";import { ReportingObserver as ReportingObserverIntegration } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new ReportingObserverIntegration({types: <'crash'|'deprecation'|'intervention'>[];})],});
CDN
<scriptsrc="https://browser.sentry-/6.12.0/bundle.min.js"integrity="sha384-S3qfdh3AsT1UN84WIYNuOX9vVOoFg3nB17Jp5/pTFGDBGBt+dtz7MGAV845efkZr"crossorigin="anonymous"></script><scriptsrc="https://browser.sentry-/6.12.0/reportingobserver.min.js"integrity="sha384-20D83MPBNSRANJFguhj0o9Qo7p9MCemwdMMQXotwA8742WuIwga85k+T7qEgIMWK"crossorigin="anonymous"></script>Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new ReportingObserver({types: <'crash'|'deprecation'|'intervention'>[];})],});
Vue Router 集成
Vue
跟踪集成允许您在初始应用程序加载期间跟踪渲染性能。
Sentry
使用mixins
功能在其生命周期阶段提供对Vue
组件的访问。
当Sentry
遇到一个名为root
的组件,它是一个顶级Vue
实例(如new Vue({})
),
我们使用我们的BrowserTracing
集成,并创建一个名为Vue Application Render
的新跨度。
一旦创建了Vue Application Render
跨度,它将等待它的所有子组件都渲染完毕,然后才将跨度标记为完成(finished
)。
所描述的检测功能将为您提供有关Vue
实例渲染性能的非常高级的信息。
但是,集成还可以提供有关特定活动期间实际发生的情况的更细粒度的详细信息。 为此,您需要指定要跟踪的组件和要侦听的钩子(/v2/api/#Options-Lifecycle-Hooks)。
您还可以为所有组件打开跟踪。但是,如果您的应用程序由数百个组件组成,则可能会相当嘈杂。
我们鼓励更具体。如果您不提供hooks
,Sentry
将跟踪组件的mount
和update
钩子。
请注意,在指定hooks
时,我们使用简单动词而不是before
和-ed
对。
例如,destroy
是正确的。beforeDestroy
和destroyed
是不正确的。
要设置Vue Tracing
集成,您首先需要配置BrowserTracing
集成本身。
有关如何执行此操作的详细信息,请查看我们的性能文档。
配置完BrowserTracing
集成后,继续配置Vue
集成本身。Sentry
将新的跟踪功能构建到原始Vue
错误处理程序集成中,因此无需添加任何新包。
您只需要提供适当的配置。
跟踪Vue
应用程序的最基本配置(仅跟踪顶级组件)如下所示:
import Vue from "vue";import * as Sentry from "@sentry/browser";import { Integrations } from "@sentry/tracing";Sentry.init({// ...integrations: [new Integrations.BrowserTracing()],// We recommend adjusting this value in production, or using tracesSampler// for finer controltracesSampleRate: 1.0,});
如果要跟踪子组件,并查看有关渲染过程的更多详细信息,请配置集成以跟踪它们:
Sentry.init({Vue,trackComponents: true,});
或者,您可以选择更多粒度:
Sentry.init({Vue,integrations: [new Integrations.BrowserTracing()],trackComponents: ["App","RwvHeader","RwvFooter","RwvArticleList","Pagination",],});
例如,如果您想知道某些组件是否在初始页面加载期间被删除,请向默认值添加一个destroy
钩子:
Sentry.init({Vue,integrations: [new Integrations.BrowserTracing()],trackComponents: ["App","RwvHeader","RwvFooter","RwvArticleList","Pagination",],hooks: ["mount", "update", "destroy"],});
您可以指定顶级活动应等待最后一个组件渲染的时间。
每个新的渲染周期都会消除超时的抖动,并从头开始计数。
一旦达到超时,跟踪就完成了,所有的信息都会发送给Sentry
。
Sentry.init({Vue,integrations: [new Integrations.BrowserTracing()],trackComponents: true,timeout: 4000,});
配置
tracingOptions: {/*** Decides whether to track components by hooking into its lifecycle methods.* Can be either set to `boolean` to enable/disable tracking for all of them.* Or to an array of specific component names (case-sensitive).* Default: false*/trackComponents: boolean | string[];/*** How long to wait (in ms) until the tracked root activity is marked as finished and sent to Sentry* Default: 2000*/timeout: number;/*** List of hooks to keep track of during component lifecycle.* Available hooks: 'activate' | 'create' | 'destroy' | 'mount' | 'unmount' | 'update'* Based on /v2/api/#Options-Lifecycle-Hooks*/hooks: string[];}
使用 Vue Router
如果您使用Vue Router
,您可以使用我们提供的集成来获得更好的transaction
名称。这是如何使用它的完整示例:
import Vue from "vue";import App from "./App";import * as Sentry from "@sentry/vue";import { Integrations } from "@sentry/tracing";import Router from "vue-router";import HelloWorld from "@/components/HelloWorld";Vue.use(Router);const Foo = { template: "<div>foo</div>" };const Bar = { template: "<div>bar</div>" };const router = new Router({routes: [{path: "/",name: "HelloWorld",component: HelloWorld,},{ path: "/foo/:id", component: Foo },{ path: "/bar", component: Bar },],});Vue.config.productionTip = false;Sentry.init({Vue: Vue,dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",tracesSampleRate: 1.0,integrations: [new Integrations.BrowserTracing({routingInstrumentation: Sentry.vueRouterInstrumentation(router),}),],trackComponents: true,});/* eslint-disable no-new */new Vue({el: "#app",router,components: { App },template: "<App/>",});
自定义集成
使用以下格式向JavaScript
添加自定义集成:
// All integration that come with an SDK can be found on Sentry.Integrations object// Custom integration must conform Integration interface: /getsentry/sentry-javascript/blob/master/packages/types/src/integration.tsSentry.init({// ...integrations: [new MyAwesomeIntegration()],});
rrweb:Session 重播
Sentry
提供了与rrweb
的概念验证集成 - 一个用于记录和重放用户会话的工具包。 这在诊断丰富的单页应用程序中的复杂用户行为时非常有用。
更多信息:
https://www.rrweb.io/https://docs.sentry.io/platforms/javascript/guides/react/configuration/filtering/#using-hintshttps://docs.sentry.io/platforms/javascript/guides/react/enriching-events/attachments/
配置
要开始,您需要添加@sentry/rrweb
和rrweb
包:
npm install --save @sentry/rrweb rrweb
接下来注册与Sentry SDK
的集成。这将根据您使用的框架而有所不同:
// If you're using one of our integration packages, like `@sentry/react` or// `@sentry/angular`, substitute its name for `@sentry/browser` hereimport * as Sentry from "@sentry/browser";import SentryRRWeb from "@sentry/rrweb";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new SentryRRWeb({// ...options}),],// ...});
捕获事件的重播后,您会在事件的“重播(Replay
)”部分下的“问题详细信息(Issue Details
)”中找到它。
更多:/getsentry/sentry-rrweb
采样
为了满足您组织的需求,您可能更喜欢对回放进行采样。最简单的方法是在初始化Sentry SDK
时做出采样决定。 例如,以下是Sentry
本身如何使用抽样来仅为员工捕获这些信息:
const hasReplays = getCurrentUser().isStaff;let integrations = [];if (hasReplays) {console.log("[sentry] Instrumenting session with rrweb");integrations.push(new SentryRRWeb());}Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations,});Sentry.setTag("rrweb.active", hasReplays ? "yes" : "no");
您会注意到我们还设置了rrweb.active
标签,这有助于我们识别附加了重播(replay
)的事件,否则我们将无法找到它们。 配置完成后,您就可以在搜索查询中简单地使用rrweb.active:yes
。
Release & 运行状况
Release
是部署到环境中的代码版本。当您向 Sentry 提供有关您的版本的信息时,您可以:
确定新版本中引入的问题和回归预测哪个提交导致了问题以及谁可能负责通过在提交消息中包含问题编号来解决问题部署代码时接收电子邮件通知
此外,release
用于将source maps
应用于被压缩的 JavaScript 以查看原始的、未转换的源代码。
绑定版本
配置客户端SDK
时包含release ID
(通常称为“版本version
”)。
release
名称不能:
包含换行符、制表符、正斜杠 (/
) 或反斜杠 (\
)是(全部)句号 (.
)、双句号 (..
) 或空格 ()超过
200
个字符
该值可以是任意的,但我们推荐以下任一命名策略:
语义版本控制:package@version
或package@version+build
(例如,my.project.name@2.3.12+1234)package
是project/app
的唯一标识符(iOS
上的CFBundleIdentifier
,Android
上的packageName
)version
是类似于semver
的结构<major>.<minor?>.<patch?>.<revision?>-<prerelease?>
(iOS
上的CFBundleShortVersionString
,Android
上的versionName
)build
是标识app
迭代的数字(iOS
上的CFBundleVersion
,Android
上的versionCode
)Commit SHA:如果您使用DVCS
,我们建议使用标识哈希 identifying hash
(例如,commit SHA
,da39a3ee5e6b4b0d3255bfef95601890afd80709
)。您可以让Sentry CLI
使用sentry-clireleases proposal-version
为支持的版本控制系统自动确定此哈希值。
每个组织的发布都是全局性的;为它们添加特定于项目的前缀,以便于区分。
Sentry.init({release: "my-project-name@2.3.12",});
在Node/npm
环境中使用JavaScript
执行此操作的一种常见方法是使用process.env.npm_package_version
,如下所示:
更多:/misc/scripts#packagejson-vars
Sentry.init({release: "my-project-name@" + process.env.npm_package_version,});
您如何使版本(version
)可用于您的代码取决于您。例如,您可以使用在构建过程中设置的环境变量。
这用release
值标记每个事件。我们建议您在部署之前告诉Sentry
一个新release
,因为这将解锁我们关于releases
的文档中讨论的更多功能。但是,如果您不这样做,Sentry
将在第一次看到具有该release ID
的事件时自动在系统中创建一个release
实体。
release:https://docs.sentry.io/product/releases/
配置您的SDK
后,您可以安装repository integration
或手动为Sentry
提供您自己的commit metadata
。 阅读我们关于设置 releases
的文档,以获取有关集成 integrations
、关联提交 associating commits
以及在部署releases
时通知Sentry
的更多信息。
设置 releases: https://docs.sentry.io/product/releases/setup/
Release 运行状况
通过观察用户采用情况、应用程序使用情况、崩溃百分比和会话数据来监控release
的运行状况。release
运行状况将深入了解与用户体验相关的崩溃和错误的影响,并通过release
详细信息、图表和过滤器揭示每个新问题的趋势。
health of releases : https://docs.sentry.io/product/releases/health/crashes:https://docs.sentry.io/product/releases/health/#crashsession data:https://docs.sentry.io/product/releases/health/#session
SDK
将在SDK
初始化时自动管理会话的开始和结束。
我们为每个页面加载创建一个会话。对于单页应用程序,我们将为每次导航更改(History API)创建一个新会话。
我们将会话标记为:
如果unhandled error
或unhandled promise rejection
冒泡到全局处理程序,则崩溃。如果SDK
捕获包含异常的事件(这包括手动捕获的错误),则会出现错误。
要接收有关用户采用的数据,例如用户崩溃率百分比和采用特定版本的用户数,请在初始化SDK
时将用户设置在initialScope
上。
默认情况下,JavaScript SDK
正在发送会话。
要禁用发送会话,请将autoSessionTracking
标志设置为false
:
Sentry.init({autoSessionTracking: false // default: true});
环境
Sentry
在收到带有environment
标签的事件时会自动创建环境。环境区分大小写。 环境名称不能包含换行符、空格或正斜杠,不能是字符串“None
”或超过64
个字符。 您无法删除环境,但可以隐藏它们。
hidden-environments: https://docs.sentry.io/product/sentry-basics/environments/#hidden-environments
Sentry.init({environment: "production",});
环境可帮助您在sentry.io
的问题详细信息页面中更好地过滤问题、版本和用户反馈,您可以在我们涵盖使用环境的文档中了解更多信息。
environments:https://docs.sentry.io/product/sentry-basics/environments/
过滤
将 Sentry 添加到您的应用程序可为您提供大量关于错误和性能的非常有价值的信息,否则您将无法获得这些信息。 大量的信息是好的——只要它是正确的信息,并且数量合理。
Sentry SDK
有几个配置选项可以帮助您过滤事件。
我们还提供入站过滤器 Inbound Filters
来过滤sentry.io
中的事件。 不过,我们建议在客户端级别进行过滤,因为它消除了发送您实际上不想要的事件的开销。 了解有关事件中可用字段的更多信息。
Inbound Filters: https://docs.sentry.io/product/data-management-settings/filtering/fields available in an event:https://develop.sentry.dev/sdk/event-payloads/
过滤错误事件
通过使用beforeSend
回调方法和配置、启用或禁用集成来配置您的SDK
以过滤错误事件。
使用 beforeSend
所有Sentry SDK
都支持beforeSend
回调方法。beforeSend
在事件发送到服务器之前立即调用,因此它是您可以编辑其数据的最后位置。它将事件对象作为参数接收,因此您可以使用该参数根据自定义逻辑和事件上可用的数据修改事件的数据或完全删除它(通过返回null
)。
Sentry.init({// ...beforeSend(event, hint) {const error = hint.originalException;if (error &&error.message &&error.message.match(/database unavailable/i)) {event.fingerprint = ["database-unavailable"];}return event;},});
还要注意,正如我们的breadcrumbs
文档中所讨论的,breadcrumbs
可以被过滤。
breadcrumbs: https://docs.sentry.io/product/error-monitoring/breadcrumbs/
Event Hints
before-send
回调传递event
和第二个参数hint
,该参数包含一个或多个hints
。
通常,hint
保存原始异常,以便可以提取附加数据或影响分组。 在本例中,如果捕获到某种类型的异常,指纹将被强制为一个公共值:
Sentry.init({// ...beforeSend(event, hint) {const error = hint.originalException;if (error &&error.message &&error.message.match(/database unavailable/i)) {event.fingerprint = ["database-unavailable"];}return event;},});
有关哪些hints
可用的信息,请参阅:
hints in JavaScript: https://docs.sentry.io/platforms/javascript/guides/react/configuration/filtering/#using-hints
当SDK
创建用于传输(transmission
)的事件或面包屑时,该传输通常是从某种源对象创建的。例如,错误事件通常是从日志记录或异常实例中创建的。为了更好地定制,SDK 将这些对象发送到某些回调(beforeSend
、beforeBreadcrumb
或 SDK 中的事件处理器系统)。
使用 Hints
Hints
可在两个地方获得:
beforeSend / beforeBreadcrumb
eventProcessors
事件和面包屑hints
是包含用于组合事件或面包屑的各种信息的对象。 通常hints
保存原始异常,以便可以提取附加数据或影响分组。
对于事件,例如event_id
、originalException
、syntheticException
(在内部用于生成更清晰的堆栈跟踪)以及您附加的任何其他任意数据。
对于面包屑,hints
的使用取决于实现。对于XHR
请求,hint
包含xhr
对象本身;对于用户交互,提示包含DOM
元素和事件名称等。
在本例中,如果捕获到某种类型的异常,指纹将被强制为一个公共值:
Sentry.init({// ...beforeSend(event, hint) {const error = hint.originalException;if (error &&error.message &&error.message.match(/database unavailable/i)) {event.fingerprint = ["database-unavailable"];}return event;},});
Hints for Events
originalException
导致Sentry SDK
创建事件的原始异常。这对于更改Sentry SDK
分组事件的方式或提取附加信息很有用。
syntheticException
当引发字符串(string
)或非错误(non-error
)对象时,Sentry 会创建一个合成异常(synthetic exception
),以便您可以获得基本的堆栈跟踪。 此异常存储在此处以供进一步提取数据。
Hints for Breadcrumbs
event
对于从浏览器事件创建的面包屑,Sentry SDK
通常将事件作为hint
提供给面包屑。例如,这可用于将目标 DOM 元素中的数据提取到面包屑中。
level / input
对于从控制台日志(console.log
)拦截创建的面包屑。 这保存了原始console log level
和log function
的原始输入数据。
response / input
对于从HTTP
请求创建的面包屑。它保存响应对象(来自fetch API
)和fetch
函数的输入参数。
request / response / event
对于从HTTP
请求创建的面包屑。这包含请求和响应对象(来自node HTTP API
)以及node event
(response
或error
)。
xhr
对于通过遗留XMLHttpRequest API
完成的HTTP
请求创建的面包屑。这保存了原始的xhr
对象。
整理 Sentry
您可以构建一个允许的域列表,这些域可能会引发可接受的异常。 例如,如果您的脚本是从加载的并且您的站点是
,您可以将
allowUrls
设置为:
Sentry.init({allowUrls: [/https?:\/\/((cdn|www)\.)?example\.com/]});
如果您想永远阻止特定的URL
,您也可以使用denyUrls
。
Note
在
5.17.0
版本之前,allowUrls
和denyUrls
分别称为whitelistUrls
和blacklistUrls
。出于向后兼容性的原因,这些选项仍受支持,但它们将在
6.0
版中删除。 有关更多信息,请参阅Inclusive Language Policy:https://develop.sentry.dev/inclusion/
此外,我们的社区还为日常事务编制了一份常见的忽略规则列表,例如Facebook
、Chrome extensions
等。 这很有用,建议您检查一下这些内容,看看它们是否适用于您。这不是我们 SDK 的默认值; 这只是一个广泛示例的一个亮点。
Here is the original gist:/impressiver/5092952
Sentry.init({ignoreErrors: [// Random plugins/extensions"top.GLOBALS",// See: //03/tale-of-unfindable-js-error.html"originalCreateNotification","canvas.contentDocument","MyApp_RemoveAllHighlights","","Can't find variable: ZiteReader","jigsaw is not defined","ComboSearch is not defined","http://loading./","atomicFindClose",// Facebook borked"fb_xd_fragment",// ISP "optimizing" proxy - `Cache-Control: no-transform` seems to// reduce this. (thanks @acdha)// See /questions/4113268"bmi_SafeAddOnload","EBCallBackMessageReceived",// See /Developer/HtmlAndGadget/Methods/JSInjection.aspx"conduitPage",],denyUrls: [// Facebook flakiness/graph\.facebook\.com/i,// Facebook blocked/connect\.facebook\.net\/en_US\/all\.js/i,// Woopra flakiness/eatdifferent\.com\.woopra-ns\.com/i,/static\.woopra\.com\/js\/woopra\.js/i,// Chrome extensions/extensions\//i,/^chrome:\/\//i,// Other plugins/127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb/webappstoolbarba\.texthelp\.com\//i,/metrics\.itunes\.apple\.com\.edgesuite\.net\//i,],});
使用采样过滤 Transaction 事件
为了防止某些transactions
被报告给Sentry
,请使用tracesSampler
配置选项,它允许您提供一个函数来评估当前transaction
并在它不是您想要的时候删除它。 (它还允许您以不同的采样率对不同的transaction
进行抽样。)
注意:tracesSampler
和tracesSampleRate
配置选项是互斥的。 如果您定义了一个tracesSampler
来过滤掉某些transaction
,您还必须通过返回您希望对它们进行采样的速率来处理未过滤transaction
的情况。
最简单的形式,仅用于过滤transaction
,它看起来像这样:
Sentry.init({// ...tracesSampler: samplingContext => {if ("...") {// Drop this transaction, by setting its sample rate to 0%return 0;} else {// Default sample rate for all others (replaces tracesSampleRate)return 0.1;}};});
关闭与清空
大多数SDK
的默认行为是在后台通过网络异步发送事件。 这意味着如果应用程序意外关闭,某些事件可能会丢失。SDK
提供了处理这种情况的机制。
close
方法可选地接受以毫秒为单位的timeout
,并返回一个promise
,该promise
在刷新所有挂起事件或timeout
生效时resolve
。
Sentry.close(2000).then(function() {// perform something after close});
调用close
后,不能再使用当前客户端。 仅在关闭应用程序之前立即调用close
很重要。
或者,flush
方法清空事件队列,同时保持客户端启用以供继续使用。
采样
将Sentry
添加到您的应用程序可为您提供大量关于错误和性能的非常有价值的信息,否则您将无法获得这些信息。 大量的信息是好的——只要它是正确的信息,并且数量合理。
采样 Error 事件
要将具有代表性的错误样本发送到Sentry
,请将SDK
配置中的sampleRate
选项设置为0
(发送的错误的0%
)和1
(发送的错误的100%
)之间的数字。 这是一个静态比率,它同样适用于所有错误。例如,要对25%
的错误进行抽样:
Sentry.init({ sampleRate: 0.25 });
更改错误采样率需要重新部署。
此外,设置
SDK
采样率会限制对事件源的可见性。为您的项目设置速率限制(仅在
volume
高时丢弃事件)可能更适合您的需求。
采样 Transaction 事件
我们建议对您的transaction
进行抽样,原因有两个:
捕获单个跟踪涉及的开销最小,但捕获每个页面加载或每个 API 请求的跟踪可能会给您的系统增加不必要的负载。启用采样可以让您更好地管理发送到 Sentry 的事件数量,因此您可以根据组织的需求定制您的数量。
选择采样率的目标是在性能和数量问题与数据准确性之间找到平衡。 您不想收集太多数据,但希望收集足够的数据以得出有意义的结论。 如果您不确定要选择什么速率,请从一个较低的值开始,随着您对流量模式和流量的了解越来越多,逐渐增加它。
配置 Transaction 采样率
Sentry SDK
有两个配置选项来控制发送到Sentry
的transaction
量,让您可以获取具有代表性的样本:
统一采样率(tracesSampleRate
): 提供均匀的事务横截面,无论它们在您的应用程序中的哪个位置或在什么情况下发生。使用默认继承(inheritance
)和优先(precedence
)行为 采样函数(tracesSampler
)其中: 以不同的速率采样不同的transaction
完全过滤掉一些transaction
修改默认优先级和继承行为
inheritance: https://docs.sentry.io/platforms/javascript/guides/react/configuration/sampling/#inheritance
precedence:https://docs.sentry.io/platforms/javascript/guides/react/configuration/sampling/#precedence
Filters:https://docs.sentry.io/platforms/javascript/guides/react/configuration/filtering/
设置统一采样率
为此,请将Sentry.init()
中的tracesSampleRate
选项设置为0
到1
之间的数字。设置此选项后,创建的每个transaction
都有该百分比的机会被发送到Sentry
。(因此,例如,如果您将tracesSampleRate
设置为0.2
,大约20%
的transaction
将被记录和发送。)看起来像这样:
Sentry.init({// ...tracesSampleRate: 0.2,});
设置采样函数
要使用采样函数,请将Sentry.init()
中的tracesSampler
选项设置为一个函数,该函数将接受samplingContext
对象并返回介于0
和1
之间的采样率。例如:
Sentry.init({// ...tracesSampler: samplingContext => {// Examine provided context data (including parent decision, if any) along// with anything in the global namespace to compute the sample rate or// sampling decision for this transactionif ("...") {// These are important - take a big samplereturn 0.5;} else if ("...") {// These are less important or happen much more frequently - only take 1%return 0.01;} else if ("...") {// These aren't something worth tracking - drop all transactions like thisreturn 0;} else {// Default sample ratereturn 0.1;}};});
为方便起见,该函数还可以返回一个布尔值。返回true
等同于返回1
,并且将保证transaction
将发送到Sentry
。返回false
相当于返回0
,并保证transaction
不会被发送到Sentry
。
采样 Context 数据
默认采样 Context 数据
在transaction
事务时传递给tracesSampler
的SamplingContext
对象中包含的信息因平台和集成(integration
)而异。
对于基于浏览器的SDK
,它至少包括以下内容:
// contents of `samplingContext`{transactionContext: {name: string; // human-readable identifier, like "GET /users"op: string; // short description of transaction type, like "pageload"}parentSampled: boolean; // if this transaction has a parent, its sampling decisionlocation: Location | WorkerLocation; // the window.location or self.location object... // custom context as passed to `startTransaction`}
自定义采样 Context 数据
使用自定义检测创建transaction
时,您可以通过将数据作为可选的第二个参数传递给startTransaction
来将数据添加到samplesContext
。 如果您希望采样器可以访问某些数据,但又不想将其作为标签(tag
)或数据(data
)附加到transaction
中,例如敏感信息或太大而无法与transaction
一起发送的信息,这将非常有用。例如:
Sentry.startTransaction({// `transactionContext` - will be recorded on transactionname: 'Search from navbar',op: 'search',tags: {testGroup: 'A3',treatmentName: 'eager load',},},// `customSamplingContext` - won't be recorded{// PIIuserId: '1231',// too big to sendresultsFromLastSearch: { ... }},);
继承
无论transaction
的抽样决策如何,该决策都将传递到其子跨度,并从那里传递到它们随后在其他服务中引起的任何transaction
。 (有关如何完成传播的更多信息,请参阅连接服务。)
Connecting Services: https://docs.sentry.io/platforms/javascript/performance/
如果当前正在创建的transaction
是那些后续事务之一(换句话说,如果它有父transaction
),则上游(父)采样决策将始终包含在采样上下文数据中,以便您的tracesSampler
可以选择是否和何时继承该决策。 (在大多数情况下,继承是正确的选择,以避免部分跟踪痕迹。)
在某些SDK
中,为了方便起见,tracesSampler
函数可以返回一个布尔值,这样如果这是所需的行为,则可以直接返回父级的决策。
tracesSampler: samplingContext => {// always inheritif (samplingContext.parentSampled !== undefined) {return samplingContext.parentSampled}...// rest of sampling logic here}
如果您使用的是tracesSampleRate
而不是tracesSampler
,则决策将始终被继承。
强制抽样决策
如果您在transaction
创建时知道是否要将transaction
发送到Sentry
,您还可以选择将采样决策直接传递给transaction
构造函数(注意,不是在customSamplingContext
对象中)。如果您这样做,transaction
将不受tracesSampleRate
的约束,也不会运行tracesSampler
,因此您可以指望通过的决策不会被覆盖。
Sentry.startTransaction({name: "Search from navbar",sampled: true,});
优先级
transaction
以多种方式结束抽样决策。
根据tracesSampleRate
中设置的静态采样率随机采样根据tracesSampler
采样函数返回的采样率随机采样tracesSampler
返回的绝对决策(100%
机会或0%
机会)如果transaction
有父级,继承其父级的抽样决策绝对决策传递给startTransaction
当有可能不止一个发挥作用时,以下优先规则适用:
如果将抽样决策传递给startTransaction
(请参阅上面的强制抽样决策),则将使用该决策,而不管其他任何事情如果定义了tracesSampler
,则将使用其决策。 它可以选择保留或忽略任何父采样决策,或使用采样上下文数据来做出自己的决策或为transaction
选择采样率。如果未定义tracesSampler
,但存在父采样决策,则将使用父采样决策。如果未定义tracesSampler
并且没有父采样决策,则将使用tracesSampleRate
。
Sentry Testkit
在为您的应用程序构建测试时,您希望断言正确的流跟踪(flow-tracking
)或错误正在发送到Sentry
,但没有真正将其发送到Sentry
服务器。 这样您就不会在测试运行或其他 CI 操作期间用错误报告淹没Sentry
。
注意:Sentry 合作伙伴Wix
维护 Sentry Testkit。
Wix:https://wix.github.io/sentry-testkit/
Sentry Testkit
是一个Sentry
插件,它允许拦截 Sentry 的report
并进一步检查正在发送的数据。它使Sentry
能够在您的应用程序中原生工作,并且通过覆盖默认Sentry
的传输机制(transport mechanism
),报告不会真正发送,而是本地记录到内存中。 这样,您可以稍后获取记录的报告以供您自己使用、验证或您在本地开发/测试环境中可能拥有的任何其他用途。
Sentry Testkit: https://wix.github.io/sentry-testkit/
安装
npm install sentry-testkit --save-dev
在测试中使用
const sentryTestkit = require("sentry-testkit");const { testkit, sentryTransport } = sentryTestkit();// initialize your Sentry instance with sentryTransportSentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",transport: sentryTransport,//... other configurations});// then run any scenario that should call Sentry.catchException(...)expect(testkit.reports()).toHaveLength(1);const report = testkit.reports()[0];expect(report).toHaveProperty(/*...*/);
您也可以在sentry-testkit
存储库的测试部分看到更多使用示例。
testing section: /wix/sentry-testkit/tree/master/test
Testkit API
Sentry Testkit 由一个非常简单直接的 API 组成。 请参阅 Sentry Testkit Docs 中的完整 API 描述和文档。
Sentry Testkit Docs: https://wix.github.io/sentry-testkit/
用法
Sentry
的SDK
与您的运行时环境挂钩,并根据平台自动报告错误、未捕获的异常和未处理的拒绝以及其他类型的错误。
关键术语:
event
是向Sentry
发送数据的一个实例。 通常,此数据是错误(error
)或异常(exception
)。issue
是一组相似的事件。事件的报告称为捕获(capturing)
。当一个事件被捕获时,它被发送到Sentry
。
最常见的捕获形式是捕获错误。可以捕获为错误的内容因平台而异。 一般来说,如果你有一些看起来像异常的东西,它可以被捕获。对于某些SDK
,您还可以省略captureException
的参数,Sentry
将尝试捕获当前异常。它对于手动向Sentry
报告错误或消息也很有用。
在捕获事件时,您还可以记录导致该事件的面包屑(breadcrumbs
)。 面包屑与事件不同:它们不会在 Sentry 中创建事件,而是会被缓冲,直到发送下一个事件。 在我们的面包屑文档中了解有关面包屑的更多信息。
breadcrumbs: https://docs.sentry.io/platforms/javascript/guides/react/enriching-events/breadcrumbs/
捕获 Errors
通过包含和配置Sentry
,我们的React SDK
会自动附加全局处理程序(global handlers
)来捕获未捕获的异常和未处理的promise
拒绝,如官方ECMAScript 6
标准中所述。您可以通过在GlobalHandlers
集成中将onunhandledrejection
选项更改为false
并手动挂接到每个事件处理程序,然后直接调用Sentry.captureException
或Sentry.captureMessage
来禁用此默认行为。
您可以将Error
对象传递给captureException()
以将其捕获为事件。也可以传递非 Error(non-Error
) 对象和字符串(string
),但请注意Sentry
中的结果事件(resulting events
)可能会丢失堆栈跟踪。
import * as Sentry from "@sentry/react";try {aFunctionThatMightFail();} catch (err) {Sentry.captureException(err);}
捕获 Messages
另一种常见的操作是捕获裸消息。消息是应该发送给Sentry
的文本信息。通常不会发出消息,但它们对某些团队很有用。
Sentry.captureMessage("Something went wrong");
设置 Level
级别 - 类似于日志级别 - 通常基于集成默认添加。 您还可以在事件中覆盖它。
要设置超出范围的级别,您可以为每个事件调用captureMessage()
:
Sentry.captureMessage("this is a debug message", "debug");
要在作用域内设置级别,您可以调用setLevel()
:
Sentry.configureScope(function(scope) {scope.setLevel(Sentry.Severity.Warning);});
或每个事件:
Sentry.withScope(function(scope) {scope.setLevel("info");Sentry.captureException("info");});
SDK 指纹
所有事件都有一个指纹。具有相同指纹的事件被组合成一个issue
。
默认情况下,Sentry
将运行一种内置分组算法,以根据事件中可用的信息(如堆栈跟踪stacktrace
、异常exception
和消息message
)生成指纹。 要扩展默认分组行为或完全更改它,您可以使用以下选项的组合:
在您的SDK
中,使用SDK
指纹识别,如下所述在您的项目中,使用指纹规则或堆栈跟踪规则Fingerprint Rules: https://docs.sentry.io/product/data-management-settings/event-grouping/fingerprint-rules/
Stack Trace Rules:https://docs.sentry.io/product/data-management-settings/event-grouping/stack-trace-rules/
在受支持的sdk中,您可以覆盖Sentry
的默认分组,该分组将指纹属性作为字符串数组传递。指纹数组的长度不受限制。这类似于指纹规则功能,它总是可用的,可以实现类似的结果。
fingerprint-rules:https://docs.sentry.io/product/data-management-settings/event-grouping/fingerprint-rules/
基本示例
在最基本的情况下,直接传递值:
function makeRequest(method, path, options) {return fetch(method, path, options).catch(function(err) {Sentry.withScope(function(scope) {// group errors together based on their request and responsescope.setFingerprint([method, path, String(err.statusCode)]);Sentry.captureException(err);});});}
您可以使用变量替换将动态值填充到通常在服务器上计算的指纹中。 例如,可以添加值{{ default }}
以将整个正常生成的分组哈希添加到指纹中。 这些值与服务器端指纹识别相同。有关更多信息,请参阅:
Variables: https://docs.sentry.io/product/data-management-settings/event-grouping/fingerprint-rules/#variables
以更大的粒度对错误进行分组
您的应用程序查询远程过程调用模型 (RPC) 接口或外部应用程序编程接口 (API) 服务,因此堆栈跟踪通常是相同的(即使传出请求非常不同)。
以下示例将进一步拆分 Sentry 将创建的默认组(由{{ default }}
表示),并考虑到错误对象的一些属性:
class MyRPCError extends Error {constructor(message, functionName, errorCode) {super(message);// The name of the RPC function that was called (e.g. "getAllBlogArticles")this.functionName = functionName;// For example a HTTP status code returned by the server.this.errorCode = errorCode;}}Sentry.init({...,beforeSend: function(event, hint) {const exception = hint.originalException;if (exception instanceof MyRPCError) {event.fingerprint = ['{{ default }}',String(exception.functionName),String(exception.errorCode)];}return event;}});
更进一步地分组错误
通用错误(例如数据库连接错误)具有许多不同的堆栈跟踪,并且永远不会组合在一起。
以下示例将通过从数组中省略{{ default }}
来完全覆盖Sentry
的分组:
class DatabaseConnectionError extends Error {}Sentry.init({...,beforeSend: function(event, hint) {const exception = hint.originalException;if (exception instanceof DatabaseConnectionError) {event.fingerprint = ['database-connection-error'];}return event;}});
Source Maps
生成 Source Maps
大多数现代JavaScript
编译器都支持source maps
。以下是一些常用工具的说明。
我们建议使用Sentry
的Webpack
插件来配置source maps
并在构建过程中自动上传它们。
sentry-webpack-plugin: /getsentry/sentry-webpack-plugin
source-map-support
要依赖 Sentry 的 source map 解析,您的代码不能使用
source-map-support
包。 该包以一种阻止我们的处理器正确解析它的方式覆盖捕获的堆栈跟踪。source-map-support:/package/source-map-support
Webpack
Sentry 提供了一个方便的Webpack
插件,可以配置source maps
并自动将它们上传到Sentry
。
要使用该插件,您首先需要安装它:
npm install --save-dev @sentry/webpack-plugin// oryarn add --dev @sentry/webpack-plugin
然后,配置它webpack.config.js
:
const SentryWebpackPlugin = require("@sentry/webpack-plugin");module.exports = {// other webpack configurationdevtool: 'source-map',plugins: [new SentryWebpackPlugin({// sentry-cli configuration - can also be done directly through sentry-cli// see https://docs.sentry.io/product/cli/configuration/ for detailsauthToken: process.env.SENTRY_AUTH_TOKEN,org: "example-org",project: "example-project",release: process.env.SENTRY_RELEASE,// other SentryWebpackPlugin configurationinclude: ".",ignore: ["node_modules", "webpack.config.js"],}),],};
此外,Webpack
插件会自动设置window.SENTRY_RELEASE
,因此您的Sentry.init
调用不需要包含release
值。
将 Webpack 插件设置为最后运行的插件;
否则,插件收到的 source maps 可能不是最终的。
高级用法
如果您更喜欢手动上传source maps
,请配置 Webpack 去输出source maps
:
module.exports = {devtool: 'source-map',output: {// Make maps auto-detectable by sentry-clifilename: "[name].js",sourceMapFilename: "[name].js.map",// Other `output` configuration},// Other webpack configuration};
如果您使用SourceMapDevToolPlugin
对 source map 生成进行更细粒度的控制,请关闭noSources
,以便 Sentry 可以在事件堆栈跟踪中显示正确的源代码上下文。
SourceMapDevToolPlugin:/plugins/source-map-dev-tool-plugin
Rollup
您可以配置Rollup
以生成source maps
,然后您可以使用sentry-cli
上传source maps
:
Rollup:/upload using sentry-cli:https://docs.sentry.io/product/cli/releases/#sentry-cli-sourcemaps
export default {entry: "./src/app.js",output: {file: "bundle.js",format: "cjs",sourceMap: true,},};
SystemJS
SystemJS
可以配置为输出source maps
,然后您可以使用 sentry-cli 上传source maps
:
builder.bundle("src/app.js", "dist/app.min.js", {minify: true,sourceMaps: true,sourceMapContents: true,});
SystemJS:/systemjs/builderupload using sentry-cli:https://docs.sentry.io/product/cli/releases/#sentry-cli-sourcemaps此示例配置将您的原始、未转换的源代码内联到生成的
source map
文件中。Sentry 需要source map
和您的原始源文件来执行反向转换。 如果您选择不内联源文件,则除了source map
外,您还必须使这些源文件可供 Sentry 使用(见下文)。
TypeScript
TypeScript 编译器可以输出source maps
,然后您可以使用sentry-cli
上传源映射。
将sourceRoot
属性配置为/
以从生成的源代码引用中去除构建路径前缀。这允许Sentry
相对于您的源根文件夹匹配源文件:
{"compilerOptions": {"sourceMap": true,"inlineSources": true,"sourceRoot": "/"}}
UglifyJS
我们强烈建议您使用更高级的打包器(或转译器),因为
UglifyJS
配置会变得非常复杂,并且很难达到预期的结果。
UglifyJS 可以配置为输出source maps
,然后您可以使用sentry-cli
上传:
uglifyjs app.js \-o app.min.js.map \--source-map url=app.min.js.map,includeSources
UglifyJS:/mishoo/UglifyJS
上传 Source Maps
Webpack
Sentry 使用releases
来将正确的source maps
与您的事件相匹配。release API 旨在允许您在 Sentry 中存储源文件(和source maps
)。
您可以在我们的 Webpack 插件的帮助下完成此操作,该插件在内部使用我们的Sentry CLI
。
从您的[Account] > API keys
创建一个新的身份验证令牌确认您在“Scopes”
下选择了project:write
使用npm
安装@sentry/webpack-plugin
使用必要的配置创建.sentryclirc
文件,如本页所述更新你的webpack.config.js
const SentryPlugin = require("@sentry/webpack-plugin");module.exports = {// ... other config above ...plugins: [new SentryPlugin({release: process.env.RELEASE,include: "./dist",}),],};
使用我们的 Sentry Webpack 插件文档了解有关插件进一步配置的更多信息。sentry-webpack-plugin:/getsentry/sentry-webpack-plugin
此外,您需要配置client
以发送release
:
Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",release: process.env.RELEASE,});
您不必使用
RELEASE
环境变量。只要您上传的版本与SDK
的init
调用的版本相匹配,您就可以以任何形式提供它们。
Releases API:https://docs.sentry.io/api/releases/
Sentry CLI
使用 sentry-cli 上传 Source Maps
使用sentry-cli
上传source maps
时,您需要设置构建系统以创建版本(release
)并上传与该版本对应的各种源文件。要让Sentry
对您的堆栈跟踪进行解码,请同时提供:
要部署的文件(换句话说,您的编译/压缩/打包(transpilation/minification/bundling)
过程的结果;例如,app.min.js
)对应的source maps
如果source map
文件不包含您的原始源代码 (sourcesContent
),您还必须提供原始源文件。 如果源文件丢失,Sentry CLI
将尝试自动将源嵌入到您的source maps
中。
Sentry
使用releases
将正确的source maps
与您的事件相匹配。
要创建新版本,请运行以下命令(例如,在发布期间):
releases:https://docs.sentry.io/product/releases/
sentry-cli releases new <release_name>
release
名称在您的组织中必须是唯一的,并且与您的SDK
初始化代码中的release
选项相匹配。然后,使用
upload-sourcemaps
命令扫描文件夹中的source maps
,处理它们,并将它们上传到Sentry
。
sentry-cli releases files <release_name> upload-sourcemaps /path/to/files
您可以通过导航到
[Project] > Project Settings > Source Maps
找到上传到Sentry
的工件。
此命令会将所有以.js
和.map
结尾的文件上传到指定的版本(release
)。如果你想改变这些扩展 — 例如,上传 typescript 源文件 — 使用--ext
选项:
sentry-cli releases files <release_name> upload-sourcemaps --ext ts --ext map /path/to/files
到目前为止,该版本处于草稿状态(“unreleased”
)。
上传所有source maps
后,您的应用程序已成功发布,使用以下命令完成release
:
sentry-cli releases finalize <release_name>
为方便起见,您可以将--finalize
标志传递给新命令,这将立即完成release
。
有关更多信息,请参阅我们的sentry-cli
文档。
sentry-cli:https://docs.sentry.io/product/cli/releases/#managing-release-artifacts
Web 应用程序可在多个来源访问的情况并不少见。 请参阅我们关于多源的文档以了解如何处理此问题。
multiple origins:https://docs.sentry.io/platforms/javascript/guides/react/sourcemaps/uploading/multiple-origins/
公开托管
将
source maps
提供给 Sentry 的最可靠方法是上传它们,因为它减少了网络流量并确保将使用正确版本的代码和源映射。
默认情况下,Sentry 将在您编译的 JavaScript 文件中查找source map
指令。这些指令位于最后一行,格式如下:
//# sourceMappingURL=<url>
当 Sentry 遇到这样的指令时,它会解析相对于它所在的源文件的 source map URL,并尝试一个 HTTP 请求来获取它。
例如,如果您有一个位于/js/app.min.js
的压缩的 JavaScript 文件,并且在该文件的最后一行,可以找到以下指令:
//# sourceMappingURL=app.js.map
Sentry 将尝试从/js/app.js.map
获取app.js.map
。
或者,在source map
生成期间,您可以指定source map
所在的完全限定URL
:
//# sourceMappingURL=/js/app.js.map
虽然从您的服务器向 Sentry 提供source maps
是最自然的集成,但并不总是可取的:
Sentry 可能并不总是能够访问您的服务器。如果您未在asset URL
中指定版本,则可能存在版本不匹配额外的延迟可能意味着源映射并非适用于所有错误。
由于这些原因,最好事先将source maps
上传到 Sentry(见下文)。
在防火墙后面工作
虽然推荐的解决方案是将您的源工件(打包转译后的代码)上传到Sentry
,但有时需要允许来自Sentry
的内部IP
的通信。
有关 Sentry public IP 的更多信息,请参阅:
IP Ranges:https://docs.sentry.io/product/security/ip-ranges/
安全访问 Source Maps
如果您想对source maps
保密并选择不将source maps
直接上传到Sentry
,您可以在项目设置中启用“Security Token”
选项。
这将导致从Sentry
的服务器发出的来自你的 “Allowed Domains” 的url
的出站请求附加 HTTP headerX-Sentry-Token
头:
GET /assets/bundle.min.jsX-Sentry-Token: {token}
token
是您在项目设置中定义的安全值。然后,您可以配置您的 Web 服务器以允许在此header/token
对存在时访问您的source maps
。 您也可以覆盖默认header
名称 (X-Sentry-Token
) 并使用HTTP Basic Authentication
,例如通过传递Authorization: Basic {encoded_password}
。
多个 Origin
Web 应用程序可在多个来源访问的情况并不少见。例如:
网站可通过https
和http
运行地理定位网址:例如、
多个静态
CDN
:如、
客户特定的域/子域
在这种情况下,相同的JavaScript
和source map
文件可能位于两个或多个不同的来源。 在这种情况下,我们建议在路径上使用我们特殊的波浪号 (~
) 前缀。
例如,如果您有以下内容:
/js/app.js/js/app.js
您可以使用~/js/app.js
的URL
上传。这将告诉Sentry
忽略域并将artifact
用于任何来源。
此外,您还可以以多个名称上传同一个文件。 在引擎盖(hood
)下 Sentry 将对这些进行重复数据删除。
~
前缀告诉Sentry
对于给定的URL
,路径为/js/app.js
的协议和主机名的任何组合都应该使用这个工件。
验证文件
确保source maps
本身有效并正确上传可能非常具有挑战性。 为了解决这个问题,我们维护了一个在线验证工具,可用于针对您的托管源测试您的source map
:sourcemaps.io
。
https://sourcemaps.io/
此外,您可以在使用sentry-cli
上传source maps
时使用--validate
标志,这将尝试在本地解析源映射并查找引用。 请注意,在已知情况下,验证标志将在设置正确时指示失败(如果您引用了外部source maps
,则验证工具将指示失败)。
除了验证步骤之外,您还可以检查这些:
确保您的文件的 URL 前缀正确。 这很容易出错。上传压缩文件的匹配source maps
。确保您在服务器上的压缩文件实际上引用了您的文件。
最佳实践
一个简单的设置
在这个简单的项目中,minified/transpiled
的文件及其source maps
位于同一目录中:
├── build/│ ├── worker.js│ ├── worker.js.map│ ├── app.js│ ├── app.js.map│ ├── index.html├── package.json├── public/│ └── index.html├── sentry.properties├── src/│ ├── app.js│ └── worker.js├── webpack.config.js
对于这个项目,我们可以使用一个简单的Sentry
配置:
const SentryWebpackPlugin = require("@sentry/webpack-plugin");// ...plugins: [new SentryWebpackPlugin({authToken: process.env.SENTRY_AUTH_TOKEN,org: "example-org",project: "example-project",include: "build",configFile: "sentry.properties",release: process.env.SENTRY_RELEASE,}),],// ...
我们建议使用Webpack
插件将source maps
集成到Sentry
。 如果您的项目中没有使用Webpack
,则可以使用Sentry CLI
。
一致的版本
要让Sentry
将错误堆栈跟踪与您的source maps
相关联,请将您的版本号定义为Webpack
插件选项或Sentry CLI
参数(无论您使用哪个)。如果您使用Sentry CLI
,您还应该在Sentry.init()
调用中定义相同的版本号。 确保版本号一致性的最简单方法是将其设置为项目中的环境变量:
# ...SENTRY_RELEASE="1.2.3"# ...
然后,如果您使用的是sentry-webpack-plugin
:
// ...new SentryWebpackPlugin({// ... other optionsrelease: process.env.SENTRY_RELEASE,});// ...
或者,如果您使用的是Sentry CLI
:
sh sentry-cli releases new "$SENTRY_RELEASE" sentry-cli releases files "$SENTRY_RELEASE" upload-sourcemaps /path/to/sourcemaps
// ...Sentry.init({// ... other optionsrelease: process.env.SENTRY_RELEASE,});// ...
正确的 Source Paths
您的release artifacts
(bundle
文件和源source maps
)的文件名应与堆栈跟踪中报告的路径匹配。 您可以使用上传配置来调整文件的名称。Webpack
插件和Sentry CLI
都有相同的选项;下面介绍了与source maps
相关的内容。还可以使用我们的RewriteFrames
集成来调整堆栈跟踪内的路径。
根据您的设置,您可能需要在开发和生产环境中为
source maps
进行不同的配置,因为堆栈跟踪中的路径可能不同。
Webpack 和 Sentry CLI 的选项
这些选项和示例将有助于集成您的source maps
。
include
此选项接受一个或多个路径来递归扫描源和*.map
文件。例如:
包括您的转译器/捆绑器输出文件的位置:include: './app/.next'
include: './build'
包括来自多个文件夹:包括:['./src', './lib']
递归搜索整个项目:include: '.'
rewrite
允许重写匹配的source maps
,以便在可能的情况下将索引映射扁平化并内联缺失的源。默认为true
。
应该启用此选项以使stripPrefix
和stripCommonPrefix
工作。
urlPrefix
此选项在所有文件名的开头添加一个公共前缀。默认为~/
,这是一个匹配任何scheme
和hostname
的通配符(http://my.web.site/path/to/script.js
的http://my.web.site/
部分)。
当应用程序的入口点(通常是浏览器端的index.html
和Node
的index.js
)位于源/源映射文件之上一个或多个级别时,此选项很有用,如下例所示:
├── build/│ ├── index.html│ ├── static/│ │ ├── app.js│ │ ├── app.js.map
在这种情况下,请按照以下示例进行配置:
// ...new SentryWebpackPlugin({// ...include: "build/static/",urlPrefix: "~/static/"// ...}),// ...
stripPrefix
此选项从sourcemap
中(例如,在sources entry
中)引用的文件名中删除给定的前缀。 当您需要修剪捆绑器/开发(bundler/development
)服务器可能添加到文件名的额外前缀时,这很有用,例如webpack://_N_E/
。
请注意,使用stripPrefix
选项不会更改上传文件的名称。 当您将目标文件的父文件夹作为不需要的前缀时,请在包含Webpack
插件选项或传递给sentry-cli
的path/to/sourcemaps
中包含要删除的部分。例如,如果您的文件存储在./build/static/js/
并且您在Webpack
插件配置中有include: "build"
,您的文件将使用类似~/static/js/bundle.js
的名称上传。如果您更新您的配置include: "build/static/js"
,您的文件将上传为~/bundle.js
(等等)。
调整帧(Frames)
或者,您可以使用Sentry
的RewriteFrames
集成来微调堆栈跟踪内的路径。
import { RewriteFrames } from "@sentry/integrations";Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [new RewriteFrames({// ... options}),],});
对 Source Maps 进行故障排除
Source maps
有时很难开始。如果您遇到问题:
验证在您的 SDK 中配置了一个 release
要定位和应用上传的source maps
,需要通过 CLI 或 API(以及随其上传的正确工件)创建release
,并且需要在您的 SDK 配置中指定新创建的release
的名称。
要验证这一点,请从Sentry UI
打开issue
并检查release
是否已配置。如果屏幕右侧的“Release”
旁边显示“not configured”
或“N/A”
(或者如果您在标签列表中没有看到release tag
),则需要返回并标记你的错误。如果设置正确,您将看到"Release: my_example_release"
。
验证工件(artifacts)已上传
正确配置您的release
并标记问题后,您可以通过导航到[Project] » Project Settings » Source Maps
找到上传到Sentry
的工件。
此外,请确保所有必要的文件都可用。要让 Sentryde-minify
堆栈跟踪,您必须同时提供minify
的文件(例如app.min.js
)和相应的source map
。如果source map
文件不包含您的原始源代码 (sourcesContent
),您必须另外提供原始源代码文件。或者,sentry-cli
会自动将源代码(如果缺少)嵌入到您的source maps
中。
验证sourceMappingURL
是否存在
一些CDN
会自动从静态文件(包括JavaScript
文件)中去除注释。 这可能会导致删除JavaScript
文件的sourceMappingURL
指令,因为它被视为注释。例如,CloudFlare
有一个名为Auto-Minify
的功能,如果启用它,它将去除sourceMappingURL
。
Auto-Minify:/an-all-new-and-improved-autominify/
仔细检查您部署的最终JavaScript
文件是否存在sourceMappingURL
。
或者,您可以在minify
的文件上设置SourceMap HTTP header
,而不是sourceMappingURL
。如果此header
存在,Sentry
将使用它来发现source map
的位置。
验证 artifact 发布值是否与您的 SDK 中配置的值匹配
每当您使用分发标识符(SDK
中的dist
配置选项)时,在source map
上传期间必须使用相同的值。相反,如果您的source map
使用dist
值上传,则必须在您的SDK
中设置相同的值。要将dist
值添加到您上传的source maps
,请使用--dist
标志和sentry-cli
或dist
选项和@sentry/webpack-plugin
。要在SDK
中设置dist
值,请使用Sentry.init()
中的dist
选项。
要验证 SDK 中的分发设置是否正确,请在Sentry UI
中打开一个issue
并检查dist
标签是否存在。对于工件,转到项目设置中的Source Maps
页面,选择您刚刚检查的事件中显示的release
,并验证dist
值(在upload time
旁边的小椭圆中)与事件上的值匹配。
验证 artifact 名称与sourceMappingURL
值匹配
bundled
或minified
的 JavaScript 文件最后一行的sourceMappingURL
注释告诉 Sentry(或浏览器)在哪里找到相应的source map
。这可以是完全限定的URL
、相对路径或文件名本身。 将artifact
上传到Sentry
时,您必须使用文件解析为的值命名源映射文件。
也就是说,如果您的文件类似于:
// -- end script.min.js//# sourceMappingURL=script.min.js.map
并托管在/js/script.min.js
,然后Sentry
将在/js/script.min.js.map
查找该source map
文件。 因此,您上传的artifact
必须命名为/js/script.min.js.map
(或~/js/script.min.js.map
)。
或者,如果您的文件类似于:
//-- end script.min.js//# sourceMappingURL=/dist/js/script.min.js.map
那么您上传的artifact
也应该命名为:
/dist/js/script.min.js.map
(或~/dist/js/script.min.js.map
)。
最后,如果您的文件类似于:
//-- end script.min.js//# sourceMappingURL=../maps/script.min.js.map
那么您上传的artifact
应命名为/dist/maps/script.min.js.map
(或~/dist/maps/script.min.js.map
)。
验证 artifact 名称与堆栈跟踪帧匹配
如果您已上传source maps
,但它们并未应用于Sentry
问题中的代码,请查看事件的JSON
并查找abs_path
以准确查看我们尝试解析文件的位置 - 对于 例如,http://localhost:8000/scripts/script.js
(对于堆栈跟踪中的每一帧,abs_path
将出现一次 - 将其与未deminified
的文件匹配。)。 可以在事件发生日期旁边的issue
页面顶部找到指向JSON
视图的链接。上传的artifact
名称必须与这些值匹配。
如果您的路径中有动态值(例如,/{some_value}/scripts/script.js
),您可能需要使用rewriteFrames
集成来更改您的abs_path
值。
使用 sentry-cli
如果您的sourceMappingURL
注释类似于:
// -- end script.min.js (located at http://localhost:8000/scripts/script.min.js)//# sourceMappingURL=script.min.js.map
正确上传这些文件的示例sentry-cli
命令如下所示(假设您在/scripts
目录中,从上一级目录运行 Web 服务器,这就是我们使用--url-prefix
选项的原因) :
sentry-cli releases files VERSION upload-sourcemaps . --url-prefix '~/scripts'
此命令上传当前目录中的所有JavaScript
文件。Sentry
中的Artifacts
页面现在应如下所示:
~/scripts/script.js~/scripts/script.min.js~/scripts/script.min.js.map
或者,您可以指定要上传的文件。 例如:
sentry-cli releases files VERSION upload-sourcemaps script.min.js script.min.js.map --url-prefix '~/scripts'
您还可以使用完全限定的 URL 上传它。例如:
sentry-cli releases files VERSION upload-sourcemaps . --url-prefix 'http://localhost:8000/scripts'
使用 API
您也可以使用API
上传artifact
。
curl -X POST \https://sentry.io/api/0/organizations/ORG_SLUG/releases/VERSION/files/ \-H 'Authorization: Bearer AUTH_TOKEN' \-H 'content-type: multipart/form-data' \-F file=@script.min.js.map \-F 'name=~/scripts/script.min.js.map'
使用 ~
~
在Sentry
中用于替换scheme
和domain
。
/dist/js/script.js
将匹配~/dist/js/script.js
或/dist/js/script.js
但不会匹配~/script.js
。
在发生错误之前验证 artifact 已上传
Sentry
期望给定版本中的源代码和source maps
在该release
中发生错误之前上传到Sentry
。
如果您在Sentry
捕获错误后上传artifact
,Sentry
将不会返回并追溯将任何源注释(source annotations
)应用于这些错误。 只有在artifact
上传后触发的新错误才会受到影响。
验证您的 source maps 是否正确构建
我们维护一个在线验证工具,可用于针对您的托管源测试您的source maps
:sourcemaps.io
。
https://sourcemaps.io/
或者,如果您使用Sentry CLI
将source maps
上传到Sentry
,您可以使用--validate
命令行选项来验证您的source maps
是否正确。
验证您的 source maps 在本地工作
如果您发现Sentry
没有正确映射文件名、行或列映射,您应该验证您的source maps
是否在本地运行。为此,您可以将Node.js
与Mozilla
的source-map library
结合使用。
/mozilla/source-map
首先,将source-map
作为npm
模块全局安装:
npm install -g source-map
然后,编写一个脚本来读取您的source map
文件并测试映射。 下面是一个例子:
var fs = require("fs"),path = require("path"),sourceMap = require("source-map");// file output by Webpack, Uglify, and so forthvar GENERATED_FILE = path.join(".", "app.min.js.map");// line and column located in your generated file (for example, the source of your error// from your minified file)var GENERATED_LINE_AND_COLUMN = { line: 1, column: 1000 };var rawSourceMap = fs.readFileSync(GENERATED_FILE).toString();new sourceMap.SourceMapConsumer(rawSourceMap).then(function(smc) {var pos = smc.originalPositionFor(GENERATED_LINE_AND_COLUMN);// should see something like:// { source: 'original.js', line: 57, column: 9, name: 'myfunc' }console.log(pos);});
如果您在本地获得与通过Sentry
获得的结果相同(不正确)的结果,请仔细检查您的source map
生成配置。
验证您的源文件不是太大
对于单个artifact
,Sentry
接受的最大文件大小为40 MB
。
用户通常会达到此限制,因为他们在临时构建阶段传输源文件。例如,在Webpack/Browserify
合并所有源文件之后,但在minification
之前。 如果可能,请发送原始源文件。
验证 artifact 没有被 gzip
Sentry API
目前仅适用于以纯文本(UTF-8
编码)形式上传的source maps
和源文件。如果文件以压缩格式(例如gzip
)上传,它们将不会被正确解释。
这有时发生在生成pre-compressed minified
文件的构建脚本和插件中。 例如,Webpack
的compression
插件。您需要禁用此类插件并在生成的source maps/source files
上传到 Sentry 后执行压缩。
/webpack/compression-webpack-plugin
验证 worker 与 Web 共享相同的卷(如果通过 Docker 运行自托管 Sentry)
Sentry 在其worker
中进行source map
计算。 这意味着worker
需要访问通过前端上传的文件。仔细检查cron worker
和web worker
是否可以从同一个磁盘读取/写入文件。
故障排除
如果您需要帮助解决Sentry JavaScript SDK integration
问题,您可以阅读此处记录的边缘案例。
调试附加数据
您可以查看事件的JSON payload
以了解Sentry
如何在事件中存储其他数据。数据的形状可能与描述不完全匹配。
有关更多详细信息,请参阅有关事件有效负载的完整文档。
https://develop.sentry.dev/sdk/event-payloads/
最大 JSON Payload 大小
maxValueLength
的默认值为250
,但如果您的消息较长,您可以根据需要调整此值。 请注意,并非每个值都受此选项影响。
CORS 属性和 Header
要了解从不同来源的脚本引发的 JavaScript 异常,请执行以下两项操作:
添加crossorigin="anonymous"
脚本属性
<script src="http://another-/app.js" crossorigin="anonymous"></script>
脚本属性告诉浏览器“anonymously”
获取目标文件。 请求此文件时,浏览器不会将潜在的用户识别信息(如cookie
或HTTP
凭据)传输到服务器。
添加Cross-Origin HTTP header
Access-Control-Allow-Origin: *
跨域资源共享 (CORS
) 是一组API
(主要是HTTP header
),用于规定文件应该如何跨域下载和提供服务。
通过设置Access-Control-Allow-Origin: *
,服务器向浏览器表明任何来源都可以获取此文件。 或者,您可以将其限制为您控制的已知来源:
Access-Control-Allow-Origin:
大多数社区CDN
正确设置了Access-Control-Allow-Origin
header。
$ curl --head /ajax/libs/jquery/2.2.0/jquery.js | \grep -i "access-control-allow-origin"Access-Control-Allow-Origin: *
意外的 OPTIONS 请求
如果您的应用程序由于执行额外的OPTIONS
请求而开始行为异常,则很可能是不需要的sentry-trace
请求header
的问题,当您在浏览器SDK
中为我们的Tracing Integration
使用过于通用的配置时可能会发生这种情况。
要解决此问题,请在SDK
初始化期间更改trackingOrigins
选项。 有关更多详细信息,请参阅我们的性能监控文档中的自动检测。
https://docs.sentry.io/platforms/javascript/performance/instrumentation/automatic-instrumentation/#tracingorigins
instrument.js
Console Log 语句的行号
如果调试时在您的控制台中显示了instrument.js
,请将Sentry
添加到您的框架黑盒设置中,例如:/@sentry/
,以便Chrome
在调试时忽略SDK
堆栈帧。
blackboxing:https://docs.sentry.io/platforms/javascript/guides/react/troubleshooting/
处理广告拦截器(Ad-Blockers)
当您使用我们的CDN
时,广告拦截或脚本拦截扩展可能会阻止我们的SDK
被正确获取和初始化。因此,对SDK API
的任何调用都将失败,并可能导致您的应用程序出现意外行为。
此外,即使正确下载并初始化SDK
,也可能会阻止需要接收捕获数据的Sentry
端点。这将阻止任何错误报告、会话运行状况或性能数据的传递,从而使其在sentry.io
中实际上不可用。
您可以通过上述多种方式解决第一个issue
。但是,端点阻塞只能使用隧道解决。
使用 tunnel 选项
隧道是一个HTTP
端点,充当Sentry
和您的应用程序之间的代理。 由于您控制此服务器,因此不会有任何发送到它的请求被阻止的风险。 当端点位于同一个源下时(尽管它不必为了隧道工作),浏览器不会将任何对端点的请求视为第三方请求。因此,这些请求将应用不同的安全措施,默认情况下不会触发广告拦截器。可以在下面找到流程的快速摘要。
从JavaScript SDK 6.7.0
版开始,您可以使用tunnel
选项告诉 SDK 将事件传送到配置的 URL,而不是使用DSN
。 这允许SDK
从查询参数中删除sentry_key
,这是广告拦截器首先阻止发送事件的主要原因之一。此选项还会阻止SDK
发送预检请求,这是需要在查询参数中发送sentry_key
的要求之一。
要启用tunnel
选项,请在Sentry.init
调用中提供相对或绝对URL
。当您使用相对URL
时,它是相对于当前来源的,这是我们推荐的形式。使用相对 URL 不会触发预检CORS
请求,因此不会阻止任何事件,因为广告拦截器不会将这些事件视为第三方请求。
Sentry.init({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",tunnel: "/tunnel",});
配置完成后,所有事件都将发送到/tunnel
端点。 但是,此解决方案需要在服务器上进行额外配置,因为现在需要解析事件并将其重定向到Sentry
。 这是您的服务器组件的示例:
<?php// Change $host appropriately if you run your own Sentry instance.$host = "sentry.io";// Set $known_project_ids to an array with your Sentry project IDs which you// want to accept through this proxy.$known_project_ids = array( );$envelope = stream_get_contents(STDIN);$pieces = explode("\n", $envelope, 2);$header = json_decode($pieces[0], true);if (isset($header["dsn"])) {$dsn = parse_url($header["dsn"]);$project_id = intval(trim($dsn["path"], "/"));if (in_array($project_id, $known_project_ids)) {$options = array('http' => array('header' => "Content-type: application/x-sentry-envelope\r\n",'method' => 'POST','content' => $envelope));echo file_get_contents("https://$host/api/$project_id/envelope/",false,stream_context_create($options));}}
// Requires .NET Core 3.1 and C# 9 or higherusing System;using System.Collections.Generic;using System.IO;using .Http;using System.Text.Json;using Microsoft.AspNetCore;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Hosting;using Microsoft.AspNetCore.Http;// Change host appropriately if you run your own Sentry instance.const string host = "sentry.io";// Set knownProjectIds to a list with your Sentry project IDs which you// want to accept through this proxy.var knownProjectIds = new HashSet<string>() { };var client = new HttpClient();WebHost.CreateDefaultBuilder(args).Configure(a =>a.Run(async context =>{context.Request.EnableBuffering();using var reader = new StreamReader(context.Request.Body);var header = await reader.ReadLineAsync();var headerJson = JsonSerializer.Deserialize<Dictionary<string, object>>(header);if (headerJson.TryGetValue("dsn", out var dsnString)&& Uri.TryCreate(dsnString.ToString(), UriKind.Absolute, out var dsn)){var projectId = dsn.AbsolutePath.Trim('/');if (knownProjectIds.Contains(projectId) && string.Equals(dsn.Host, host, StringComparison.OrdinalIgnoreCase)) {context.Request.Body.Position = 0;await client.PostAsync($"https://{dsn.Host}/api/{projectId}/envelope/",new StreamContent(context.Request.Body));}}})).Build().Run();
查看我们的示例存储库以了解更多信息。
/getsentry/examples/tree/master/tunneling
如果您的用例与 SDK 包本身被阻止有关,以下任何一种解决方案都可以帮助您解决此问题。
直接使用 Package
处理脚本阻塞扩展的最佳方法是直接通过npm
使用SDK
包并将其与您的应用程序捆绑在一起。 这样,您就可以确保代码始终如您所愿。
第二种方法是从我们的CDN
下载SDK
并自己托管。这样,SDK
仍将与您的其余代码分开,但您可以确定它不会被阻止,因为它的来源将与您网站的来源相同。
您可以使用curl
或任何其他类似工具轻松获取它:
curl https://browser.sentry-/5.20.1/bundle.min.js -o sentry.browser.5.20.1.min.js -s
使用 JavaScript Proxy API
最后一个选项是使用Proxy
保护,这将确保您的代码不会中断,即使您调用我们的 SDK,它被阻止。 除了 Internet Explorer 之外的所有浏览器都支持Proxy
。此外,如果Proxy
不在您用户的任何浏览器中,它将被悄悄跳过,因此您不必担心它会破坏任何内容。
将此代码段直接放在包含我们的CDN
包的<script>
标签上方。可读格式的代码片段如下所示:
if ("Proxy" in window) {var handler = {get: function(_, key) {return new Proxy(function(cb) {if (key === "flush" || key === "close") return Promise.resolve();if (typeof cb === "function") return cb(window.Sentry);return window.Sentry;}, handler);},};window.Sentry = new Proxy({}, handler);}
如果您想直接复制和粘贴代码段,这里将其minified
:
<script>if ("Proxy" in window) {var n = {get: function(o, e) {return new Proxy(function(n) {return "flush" === e || "close" === e? Promise.resolve(): "function" == typeof n? n(window.Sentry): window.Sentry;}, n);},};window.Sentry = new Proxy({}, n);}</script>
直接使用 Client
为了能够管理多个Sentry
实例而它们之间没有任何冲突,您需要创建自己的Client
。 如果您的应用程序集成在其中,这也有助于防止跟踪任何父应用程序错误。在这个例子中,我们使用@sentry/browser
但它也适用于@sentry/node
。
import { BrowserClient } from "@sentry/browser";const client = new BrowserClient({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",});client.captureException(new Error("example"));
虽然上面的示例应该可以正常工作,但Client
上缺少一些方法,如configureScope
和withScope
,因为Hub
负责状态管理。这就是为什么创建新Hub
并将Client
绑定到它可能更容易的原因。结果是一样的,但你也会得到状态管理。
import { BrowserClient, Hub } from "@sentry/browser";const client = new BrowserClient({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",});const hub = new Hub(client);hub.configureScope(function(scope) {scope.setTag("a", "b");});hub.addBreadcrumb({ message: "crumb 1" });hub.captureMessage("test");try {a = b;} catch (e) {hub.captureException(e);}hub.withScope(function(scope) {hub.addBreadcrumb({ message: "crumb 2" });hub.captureMessage("test2");});
处理集成
集成是在Client
上设置的,如果您需要处理多个Client
和Hub
,您还必须确保正确进行集成处理。这是一个如何使用多个Client
和多个运行全局集成的Hub
的工作示例。
import * as Sentry from "@sentry/browser";// Very happy integration that'll prepend and append very happy stick figure to the messageclass HappyIntegration {constructor() {this.name = "HappyIntegration";}setupOnce() {Sentry.addGlobalEventProcessor(event => {const self = Sentry.getCurrentHub().getIntegration(HappyIntegration);// Run the integration ONLY when it was installed on the current Hubif (self) {event.message = `\\o/ ${event.message} \\o/`;}return event;});}}HappyIntegration.id = "HappyIntegration";const client1 = new Sentry.BrowserClient({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",integrations: [...Sentry.defaultIntegrations, new HappyIntegration()],beforeSend(event) {console.log("client 1", event);return null; // Returning null does not send the event},});const hub1 = new Sentry.Hub(client1);const client2 = new Sentry.BrowserClient({dsn: "https://examplePublicKey@o0.ingest.sentry.io/0", // Can be a different DSNintegrations: [...Sentry.defaultIntegrations, new HappyIntegration()],beforeSend(event) {console.log("client 2", event);return null; // Returning null does not send the event},});const hub2 = new Sentry.Hub(client2);hub1.run(currentHub => {// The hub.run method makes sure that Sentry.getCurrentHub() returns this hub during the callbackcurrentHub.captureMessage("a");currentHub.configureScope(function(scope) {scope.setTag("a", "b");});});hub2.run(currentHub => {// The hub.run method makes sure that Sentry.getCurrentHub() returns this hub during the callbackcurrentHub.captureMessage("x");currentHub.configureScope(function(scope) {scope.setTag("c", "d");});});
第三方 Promise 库
当您包含和配置Sentry
时,我们的JavaScript SDK
会自动附加global handlers
以capture
未捕获的exceptions
和未处理的promise rejections
。 您可以通过在GlobalHandlers
集成中将onunhandledrejection
选项更改为false
并手动挂接到每个事件处理程序,然后直接调用Sentry.captureException
或Sentry.captureMessage
来禁用此默认行为。
如果您使用第三方库来实现Promise
,您可能还需要管理您的配置。 此外,请记住,浏览器通常会实施安全措施,在提供来自不同来源的脚本文件时阻止错误报告。
具有“非错误异常Non-Error Exception
”的事件
如果您看到错误消息“Non-Error exception (or promise rejection) captured with keys: x, y, z.”
,这会发生在您a
) 使用plain object
调用Sentry.captureException()
时,b) 抛出一个plain object
,或者c
) 拒绝一个带有plain object
的promise
。
您可以在“Additional Data”
部分的__serialized__
条目中查看有问题的非错误对象的内容。
为了更好地了解这些错误事件,我们建议根据__serialized__
数据的内容找到plain object
被传递或抛出到Sentry
的位置,然后将plain object
转换为Error
对象。
支持的浏览器
Sentry
的JavaScript SDK
支持以下浏览器:
支持 <= IE 11
在5.7.0
版本之前,我们的JavaScript SDK
需要一些polyfills
用于旧版浏览器,如IE 11
及更低版本。如果您正在使用它,请在加载我们的SDK
之前升级到最新版本或添加下面的脚本标签。
<script src="https://polyfill.io/v3/polyfill.min.js?features=Promise%2CObject.assign%2CString.prototype.includes%2CNumber.isNaN"></script>
我们需要以下polyfill
:
Promise
Object.assign
Number.isNaN
String.prototype.includes
此外,请记住在HTML
页面顶部定义有效的HTML doctype
,以确保IE
不会进入兼容模式(compatibility mode)
。
公众号:黑客下午茶