@danieljvdm/dev-kit 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/README.md +6 -6
  2. package/package.json +1 -1
  3. package/skill-sources.jsonc +2 -33
  4. package/skill-sources.lock.json +15 -117
  5. package/skills/animate/LICENSE +21 -0
  6. package/skills/animate/NOTICE +10 -0
  7. package/skills/animate/SKILL.md +34 -0
  8. package/skills/animate/references/gestures.md +27 -0
  9. package/skills/animate/references/glossary.md +136 -0
  10. package/skills/animate/references/implementation.md +22 -0
  11. package/skills/animate/references/opportunities.md +18 -0
  12. package/skills/animate/references/principles.md +48 -0
  13. package/skills/animate/references/review.md +19 -0
  14. package/skills/cloudflare-workers/LICENSE +202 -0
  15. package/skills/cloudflare-workers/NOTICE +9 -0
  16. package/skills/cloudflare-workers/SKILL.md +26 -0
  17. package/skills/cloudflare-workers/references/durable-objects.md +68 -0
  18. package/skills/cloudflare-workers/references/sandbox.md +48 -0
  19. package/skills/cloudflare-workers/references/workers.md +63 -0
  20. package/skills/cloudflare-workers/references/wrangler.md +56 -0
  21. package/skills/design-ui/LICENSE +21 -0
  22. package/skills/design-ui/NOTICE +8 -0
  23. package/skills/design-ui/SKILL.md +29 -0
  24. package/skills/design-ui/references/appearance.md +22 -0
  25. package/skills/design-ui/references/components.md +33 -0
  26. package/skills/design-ui/references/exploration.md +50 -0
  27. package/skills/design-ui/references/libraries.md +39 -0
  28. package/skills/design-ui/references/themes.md +23 -0
  29. package/skills/dev-kit/SKILL.md +19 -38
  30. package/skills/dev-kit/references/cloudflare-worker-api.md +1 -1
  31. package/skills/dev-kit/references/skills.md +2 -2
  32. package/skills/effect-development/SKILL.md +27 -0
  33. package/skills/effect-development/agents/openai.yaml +4 -0
  34. package/skills/effect-development/references/api/index.md +32 -0
  35. package/skills/effect-development/references/api/schema-codecs.md +15 -0
  36. package/skills/{build-effect-apis/references → effect-development/references/api}/verification.md +10 -5
  37. package/skills/{effect-architecture-audit/SKILL.md → effect-development/references/architecture/index.md} +1 -6
  38. package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-client.md +8 -6
  39. package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-testing.md +7 -2
  40. package/skills/effect-development/references/atom/index.md +40 -0
  41. package/skills/{build-effect-clis/references → effect-development/references/cli}/entrypoints-and-testing.md +6 -2
  42. package/skills/effect-development/references/cli/index.md +39 -0
  43. package/skills/effect-development/references/setup.md +15 -0
  44. package/skills/open-pull-request/SKILL.md +10 -70
  45. package/skills/open-pull-request/references/evidence.md +22 -0
  46. package/skills/open-pull-request/references/explanation.md +21 -0
  47. package/skills/open-pull-request/references/publication.md +21 -0
  48. package/skills/sentry/LICENSE +202 -0
  49. package/skills/sentry/LICENSE-UPSTREAM +21 -0
  50. package/skills/sentry/NOTICE +14 -0
  51. package/skills/sentry/SKILL.md +33 -0
  52. package/skills/sentry/references/alert-payloads.md +105 -0
  53. package/skills/sentry/references/alerts.md +17 -0
  54. package/skills/sentry/references/artifacts.md +25 -0
  55. package/skills/sentry/references/auth-token.md +65 -0
  56. package/skills/sentry/references/concepts/ai-monitoring.md +131 -0
  57. package/skills/sentry/references/concepts/choosing-a-signal.md +78 -0
  58. package/skills/sentry/references/concepts/crons.md +50 -0
  59. package/skills/sentry/references/concepts/data-scrubbing.md +43 -0
  60. package/skills/sentry/references/concepts/errors.md +40 -0
  61. package/skills/sentry/references/concepts/logging.md +85 -0
  62. package/skills/sentry/references/concepts/metrics.md +49 -0
  63. package/skills/sentry/references/concepts/monitors.md +78 -0
  64. package/skills/sentry/references/concepts/profiling.md +38 -0
  65. package/skills/sentry/references/concepts/reduce-volume.md +49 -0
  66. package/skills/sentry/references/concepts/releases.md +43 -0
  67. package/skills/sentry/references/concepts/session-replay.md +35 -0
  68. package/skills/sentry/references/concepts/tracing.md +54 -0
  69. package/skills/sentry/references/concepts/user-feedback.md +36 -0
  70. package/skills/sentry/references/debug-artifacts/android.md +68 -0
  71. package/skills/sentry/references/debug-artifacts/apple.md +96 -0
  72. package/skills/sentry/references/debug-artifacts/dotnet.md +70 -0
  73. package/skills/sentry/references/debug-artifacts/flutter.md +65 -0
  74. package/skills/sentry/references/debug-artifacts/index.md +75 -0
  75. package/skills/sentry/references/debug-artifacts/javascript.md +94 -0
  76. package/skills/sentry/references/debug-artifacts/matching.md +73 -0
  77. package/skills/sentry/references/debug-artifacts/react-native.md +75 -0
  78. package/skills/sentry/references/first-error-setup.md +25 -0
  79. package/skills/sentry/references/instrumentation.md +30 -0
  80. package/skills/sentry/references/issues.md +32 -0
  81. package/skills/sentry/references/new-project.md +17 -0
  82. package/skills/sentry/references/otel-exporter.md +30 -0
  83. package/skills/sentry/references/release-workflow.md +31 -0
  84. package/skills/sentry/references/releases/ci-pipeline.md +214 -0
  85. package/skills/sentry/references/releases/index.md +93 -0
  86. package/skills/sentry/references/releases/suspect-commits.md +155 -0
  87. package/skills/sentry/references/releases/tagging.md +131 -0
  88. package/skills/sentry/references/releases/troubleshooting.md +67 -0
  89. package/skills/sentry/references/sdks/android/crons.md +305 -0
  90. package/skills/sentry/references/sdks/android/error-monitoring.md +800 -0
  91. package/skills/sentry/references/sdks/android/index.md +748 -0
  92. package/skills/sentry/references/sdks/android/integrations.md +48 -0
  93. package/skills/sentry/references/sdks/android/logging.md +374 -0
  94. package/skills/sentry/references/sdks/android/metrics.md +288 -0
  95. package/skills/sentry/references/sdks/android/profiling.md +397 -0
  96. package/skills/sentry/references/sdks/android/session-replay.md +406 -0
  97. package/skills/sentry/references/sdks/android/tracing.md +861 -0
  98. package/skills/sentry/references/sdks/browser/error-monitoring.md +861 -0
  99. package/skills/sentry/references/sdks/browser/index.md +714 -0
  100. package/skills/sentry/references/sdks/browser/logging.md +315 -0
  101. package/skills/sentry/references/sdks/browser/profiling.md +236 -0
  102. package/skills/sentry/references/sdks/browser/session-replay.md +586 -0
  103. package/skills/sentry/references/sdks/browser/tracing.md +561 -0
  104. package/skills/sentry/references/sdks/browser/user-feedback.md +354 -0
  105. package/skills/sentry/references/sdks/cloudflare/ai-monitoring.md +661 -0
  106. package/skills/sentry/references/sdks/cloudflare/crons.md +231 -0
  107. package/skills/sentry/references/sdks/cloudflare/durable-objects.md +381 -0
  108. package/skills/sentry/references/sdks/cloudflare/error-monitoring.md +329 -0
  109. package/skills/sentry/references/sdks/cloudflare/index.md +698 -0
  110. package/skills/sentry/references/sdks/cloudflare/logging.md +169 -0
  111. package/skills/sentry/references/sdks/cloudflare/nodejs-compat.md +134 -0
  112. package/skills/sentry/references/sdks/cloudflare/tracing.md +475 -0
  113. package/skills/sentry/references/sdks/cocoa/error-monitoring.md +394 -0
  114. package/skills/sentry/references/sdks/cocoa/index.md +497 -0
  115. package/skills/sentry/references/sdks/cocoa/logging.md +209 -0
  116. package/skills/sentry/references/sdks/cocoa/metrics.md +136 -0
  117. package/skills/sentry/references/sdks/cocoa/profiling.md +223 -0
  118. package/skills/sentry/references/sdks/cocoa/session-replay.md +257 -0
  119. package/skills/sentry/references/sdks/cocoa/tracing.md +524 -0
  120. package/skills/sentry/references/sdks/cocoa/user-feedback.md +310 -0
  121. package/skills/sentry/references/sdks/dotnet/crons.md +465 -0
  122. package/skills/sentry/references/sdks/dotnet/error-monitoring.md +1100 -0
  123. package/skills/sentry/references/sdks/dotnet/index.md +614 -0
  124. package/skills/sentry/references/sdks/dotnet/logging.md +556 -0
  125. package/skills/sentry/references/sdks/dotnet/metrics.md +229 -0
  126. package/skills/sentry/references/sdks/dotnet/profiling.md +296 -0
  127. package/skills/sentry/references/sdks/dotnet/tracing.md +897 -0
  128. package/skills/sentry/references/sdks/elixir/crons.md +371 -0
  129. package/skills/sentry/references/sdks/elixir/error-monitoring.md +335 -0
  130. package/skills/sentry/references/sdks/elixir/index.md +383 -0
  131. package/skills/sentry/references/sdks/elixir/logging.md +239 -0
  132. package/skills/sentry/references/sdks/elixir/tracing.md +233 -0
  133. package/skills/sentry/references/sdks/flutter/ecosystem-integrations.md +70 -0
  134. package/skills/sentry/references/sdks/flutter/error-monitoring.md +312 -0
  135. package/skills/sentry/references/sdks/flutter/index.md +728 -0
  136. package/skills/sentry/references/sdks/flutter/logging.md +387 -0
  137. package/skills/sentry/references/sdks/flutter/metrics.md +310 -0
  138. package/skills/sentry/references/sdks/flutter/profiling.md +214 -0
  139. package/skills/sentry/references/sdks/flutter/session-replay.md +308 -0
  140. package/skills/sentry/references/sdks/flutter/tracing.md +502 -0
  141. package/skills/sentry/references/sdks/go/crons.md +270 -0
  142. package/skills/sentry/references/sdks/go/error-monitoring.md +361 -0
  143. package/skills/sentry/references/sdks/go/index.md +324 -0
  144. package/skills/sentry/references/sdks/go/logging.md +354 -0
  145. package/skills/sentry/references/sdks/go/metrics.md +273 -0
  146. package/skills/sentry/references/sdks/go/profiling.md +46 -0
  147. package/skills/sentry/references/sdks/go/tracing.md +366 -0
  148. package/skills/sentry/references/sdks/index.md +41 -0
  149. package/skills/sentry/references/sdks/nestjs/ai-monitoring.md +410 -0
  150. package/skills/sentry/references/sdks/nestjs/crons.md +268 -0
  151. package/skills/sentry/references/sdks/nestjs/error-monitoring.md +729 -0
  152. package/skills/sentry/references/sdks/nestjs/index.md +699 -0
  153. package/skills/sentry/references/sdks/nestjs/logging.md +174 -0
  154. package/skills/sentry/references/sdks/nestjs/metrics.md +243 -0
  155. package/skills/sentry/references/sdks/nestjs/profiling.md +127 -0
  156. package/skills/sentry/references/sdks/nestjs/tracing.md +762 -0
  157. package/skills/sentry/references/sdks/nextjs/ai-monitoring.md +494 -0
  158. package/skills/sentry/references/sdks/nextjs/crons.md +383 -0
  159. package/skills/sentry/references/sdks/nextjs/error-monitoring.md +974 -0
  160. package/skills/sentry/references/sdks/nextjs/index.md +491 -0
  161. package/skills/sentry/references/sdks/nextjs/logging.md +381 -0
  162. package/skills/sentry/references/sdks/nextjs/metrics.md +411 -0
  163. package/skills/sentry/references/sdks/nextjs/profiling.md +403 -0
  164. package/skills/sentry/references/sdks/nextjs/session-replay.md +462 -0
  165. package/skills/sentry/references/sdks/nextjs/tracing.md +628 -0
  166. package/skills/sentry/references/sdks/node/ai-monitoring.md +303 -0
  167. package/skills/sentry/references/sdks/node/crons.md +432 -0
  168. package/skills/sentry/references/sdks/node/error-monitoring.md +1125 -0
  169. package/skills/sentry/references/sdks/node/index.md +942 -0
  170. package/skills/sentry/references/sdks/node/logging.md +380 -0
  171. package/skills/sentry/references/sdks/node/metrics.md +278 -0
  172. package/skills/sentry/references/sdks/node/profiling.md +373 -0
  173. package/skills/sentry/references/sdks/node/tracing.md +878 -0
  174. package/skills/sentry/references/sdks/php/ai-monitoring.md +310 -0
  175. package/skills/sentry/references/sdks/php/crons.md +265 -0
  176. package/skills/sentry/references/sdks/php/error-monitoring.md +626 -0
  177. package/skills/sentry/references/sdks/php/index.md +362 -0
  178. package/skills/sentry/references/sdks/php/laravel.md +542 -0
  179. package/skills/sentry/references/sdks/php/logging.md +242 -0
  180. package/skills/sentry/references/sdks/php/metrics.md +193 -0
  181. package/skills/sentry/references/sdks/php/profiling.md +115 -0
  182. package/skills/sentry/references/sdks/php/symfony.md +552 -0
  183. package/skills/sentry/references/sdks/php/tracing.md +516 -0
  184. package/skills/sentry/references/sdks/python/ai-monitoring.md +351 -0
  185. package/skills/sentry/references/sdks/python/crons.md +218 -0
  186. package/skills/sentry/references/sdks/python/error-monitoring.md +292 -0
  187. package/skills/sentry/references/sdks/python/index.md +361 -0
  188. package/skills/sentry/references/sdks/python/logging.md +234 -0
  189. package/skills/sentry/references/sdks/python/metrics.md +154 -0
  190. package/skills/sentry/references/sdks/python/profiling.md +120 -0
  191. package/skills/sentry/references/sdks/python/tracing.md +364 -0
  192. package/skills/sentry/references/sdks/react/error-monitoring.md +1607 -0
  193. package/skills/sentry/references/sdks/react/index.md +492 -0
  194. package/skills/sentry/references/sdks/react/logging.md +364 -0
  195. package/skills/sentry/references/sdks/react/profiling.md +322 -0
  196. package/skills/sentry/references/sdks/react/react-features.md +1272 -0
  197. package/skills/sentry/references/sdks/react/session-replay.md +1193 -0
  198. package/skills/sentry/references/sdks/react/tracing.md +1415 -0
  199. package/skills/sentry/references/sdks/react-native/error-monitoring.md +1481 -0
  200. package/skills/sentry/references/sdks/react-native/expo-config-plugin.md +45 -0
  201. package/skills/sentry/references/sdks/react-native/index.md +1030 -0
  202. package/skills/sentry/references/sdks/react-native/logging.md +444 -0
  203. package/skills/sentry/references/sdks/react-native/profiling.md +386 -0
  204. package/skills/sentry/references/sdks/react-native/session-replay.md +704 -0
  205. package/skills/sentry/references/sdks/react-native/tracing.md +1086 -0
  206. package/skills/sentry/references/sdks/react-native/user-feedback.md +815 -0
  207. package/skills/sentry/references/sdks/react-router-framework/error-monitoring.md +127 -0
  208. package/skills/sentry/references/sdks/react-router-framework/index.md +411 -0
  209. package/skills/sentry/references/sdks/react-router-framework/logging.md +66 -0
  210. package/skills/sentry/references/sdks/react-router-framework/profiling.md +57 -0
  211. package/skills/sentry/references/sdks/react-router-framework/react-router-framework-features.md +110 -0
  212. package/skills/sentry/references/sdks/react-router-framework/session-replay.md +67 -0
  213. package/skills/sentry/references/sdks/react-router-framework/tracing.md +96 -0
  214. package/skills/sentry/references/sdks/react-router-framework/user-feedback.md +71 -0
  215. package/skills/sentry/references/sdks/ruby/crons.md +184 -0
  216. package/skills/sentry/references/sdks/ruby/error-monitoring.md +248 -0
  217. package/skills/sentry/references/sdks/ruby/index.md +297 -0
  218. package/skills/sentry/references/sdks/ruby/logging.md +168 -0
  219. package/skills/sentry/references/sdks/ruby/metrics.md +196 -0
  220. package/skills/sentry/references/sdks/ruby/migration.md +321 -0
  221. package/skills/sentry/references/sdks/ruby/profiling.md +107 -0
  222. package/skills/sentry/references/sdks/ruby/tracing.md +388 -0
  223. package/skills/sentry/references/sdks/svelte/error-monitoring.md +456 -0
  224. package/skills/sentry/references/sdks/svelte/index.md +467 -0
  225. package/skills/sentry/references/sdks/svelte/logging.md +344 -0
  226. package/skills/sentry/references/sdks/svelte/session-replay.md +369 -0
  227. package/skills/sentry/references/sdks/svelte/tracing.md +406 -0
  228. package/skills/sentry/references/sdks/tanstack-start/error-monitoring.md +149 -0
  229. package/skills/sentry/references/sdks/tanstack-start/index.md +381 -0
  230. package/skills/sentry/references/sdks/tanstack-start/logging.md +74 -0
  231. package/skills/sentry/references/sdks/tanstack-start/session-replay.md +76 -0
  232. package/skills/sentry/references/sdks/tanstack-start/tanstackstart-features.md +128 -0
  233. package/skills/sentry/references/sdks/tanstack-start/tracing.md +123 -0
  234. package/skills/sentry/references/sdks/tanstack-start/user-feedback.md +81 -0
  235. package/skills/sentry/references/search-query-language.md +226 -0
  236. package/skills/sentry/references/semantics/angular.md +7 -0
  237. package/skills/sentry/references/semantics/app.md +28 -0
  238. package/skills/sentry/references/semantics/art.md +17 -0
  239. package/skills/sentry/references/semantics/aws.md +43 -0
  240. package/skills/sentry/references/semantics/browser.md +34 -0
  241. package/skills/sentry/references/semantics/cache.md +12 -0
  242. package/skills/sentry/references/semantics/client.md +8 -0
  243. package/skills/sentry/references/semantics/cloud.md +12 -0
  244. package/skills/sentry/references/semantics/cloudflare.md +23 -0
  245. package/skills/sentry/references/semantics/code.md +11 -0
  246. package/skills/sentry/references/semantics/culture.md +11 -0
  247. package/skills/sentry/references/semantics/db.md +21 -0
  248. package/skills/sentry/references/semantics/device.md +43 -0
  249. package/skills/sentry/references/semantics/error.md +7 -0
  250. package/skills/sentry/references/semantics/event.md +8 -0
  251. package/skills/sentry/references/semantics/exception.md +10 -0
  252. package/skills/sentry/references/semantics/faas.md +19 -0
  253. package/skills/sentry/references/semantics/file.md +8 -0
  254. package/skills/sentry/references/semantics/flag.md +7 -0
  255. package/skills/sentry/references/semantics/gcp.md +16 -0
  256. package/skills/sentry/references/semantics/gen_ai.md +53 -0
  257. package/skills/sentry/references/semantics/general.md +11 -0
  258. package/skills/sentry/references/semantics/graphql.md +9 -0
  259. package/skills/sentry/references/semantics/grpc.md +19 -0
  260. package/skills/sentry/references/semantics/http.md +34 -0
  261. package/skills/sentry/references/semantics/index.md +63 -0
  262. package/skills/sentry/references/semantics/jsonrpc.md +8 -0
  263. package/skills/sentry/references/semantics/jvm.md +12 -0
  264. package/skills/sentry/references/semantics/koa.md +7 -0
  265. package/skills/sentry/references/semantics/logger.md +7 -0
  266. package/skills/sentry/references/semantics/mcp.md +37 -0
  267. package/skills/sentry/references/semantics/mdc.md +7 -0
  268. package/skills/sentry/references/semantics/messaging.md +23 -0
  269. package/skills/sentry/references/semantics/middleware.md +7 -0
  270. package/skills/sentry/references/semantics/navigation.md +9 -0
  271. package/skills/sentry/references/semantics/nel.md +11 -0
  272. package/skills/sentry/references/semantics/network.md +17 -0
  273. package/skills/sentry/references/semantics/os.md +15 -0
  274. package/skills/sentry/references/semantics/otel.md +10 -0
  275. package/skills/sentry/references/semantics/params.md +7 -0
  276. package/skills/sentry/references/semantics/process.md +14 -0
  277. package/skills/sentry/references/semantics/react.md +7 -0
  278. package/skills/sentry/references/semantics/remix.md +7 -0
  279. package/skills/sentry/references/semantics/resource.md +7 -0
  280. package/skills/sentry/references/semantics/rpc.md +10 -0
  281. package/skills/sentry/references/semantics/score.md +10 -0
  282. package/skills/sentry/references/semantics/sentry.md +69 -0
  283. package/skills/sentry/references/semantics/server.md +8 -0
  284. package/skills/sentry/references/semantics/service.md +8 -0
  285. package/skills/sentry/references/semantics/session.md +7 -0
  286. package/skills/sentry/references/semantics/state.md +7 -0
  287. package/skills/sentry/references/semantics/thread.md +8 -0
  288. package/skills/sentry/references/semantics/timber.md +7 -0
  289. package/skills/sentry/references/semantics/trpc.md +8 -0
  290. package/skills/sentry/references/semantics/ui.md +18 -0
  291. package/skills/sentry/references/semantics/url.md +15 -0
  292. package/skills/sentry/references/semantics/user.md +17 -0
  293. package/skills/sentry/references/semantics/user_agent.md +7 -0
  294. package/skills/sentry/references/semantics/vercel.md +42 -0
  295. package/skills/sentry/references/setup-verification.md +39 -0
  296. package/skills/sentry/references/snapshots/github-actions-fanout.md +206 -0
  297. package/skills/sentry/references/snapshots/github-actions-simple.md +102 -0
  298. package/skills/sentry/references/snapshots/github-actions-swift-snapshot-testing.md +118 -0
  299. package/skills/sentry/references/snapshots/index.md +19 -0
  300. package/skills/sentry/references/snapshots/snapshot-previews.md +100 -0
  301. package/skills/sentry/references/snapshots/snapshots.md +123 -0
  302. package/skills/sentry/references/snapshots/wizard-setup.md +134 -0
  303. package/skills/testing/LICENSE +21 -0
  304. package/skills/testing/NOTICE +7 -0
  305. package/skills/testing/SKILL.md +13 -19
  306. package/skills/testing/agents/openai.yaml +1 -2
  307. package/skills/testing/references/selection.md +23 -0
  308. package/skills/testing/references/tdd.md +19 -0
  309. package/skills/testing/references/test-design.md +17 -0
  310. package/src/catalog.ts +1 -7
  311. package/skills/build-effect-apis/SKILL.md +0 -81
  312. package/skills/build-effect-apis/agents/openai.yaml +0 -4
  313. package/skills/build-effect-clis/SKILL.md +0 -92
  314. package/skills/build-effect-clis/agents/openai.yaml +0 -4
  315. package/skills/effect-architecture-audit/agents/openai.yaml +0 -4
  316. package/skills/effect-atom-state/SKILL.md +0 -97
  317. package/skills/effect-atom-state/agents/openai.yaml +0 -4
  318. package/skills/effect-ts/SKILL.md +0 -35
  319. package/skills/effect-ts/agents/openai.yaml +0 -4
  320. /package/skills/{build-effect-apis/references → effect-development/references/api}/cloudflare-workers.md +0 -0
  321. /package/skills/{build-effect-apis/references → effect-development/references/api}/runtime-assembly.md +0 -0
  322. /package/skills/{build-effect-apis/references → effect-development/references/api}/server-and-middleware.md +0 -0
  323. /package/skills/{build-effect-apis/references → effect-development/references/api}/shared-contracts.md +0 -0
  324. /package/skills/{effect-architecture-audit/references → effect-development/references/architecture}/service-and-boundary-audit.md +0 -0
  325. /package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-lifecycle.md +0 -0
  326. /package/skills/{effect-atom-state/references → effect-development/references/atom}/effect-atom-workflows.md +0 -0
  327. /package/skills/{effect-atom-state/references → effect-development/references/atom}/tanstack-start.md +0 -0
  328. /package/skills/{build-effect-clis/references → effect-development/references/cli}/command-design.md +0 -0
  329. /package/skills/{build-effect-clis/references → effect-development/references/cli}/processes-and-platform.md +0 -0
@@ -0,0 +1,1415 @@
1
+ # Tracing — Sentry React SDK
2
+
3
+ > Minimum SDK: `@sentry/react` ≥8.0.0+\
4
+ > `reactRouterV7BrowserTracingIntegration`: requires `@sentry/react` ≥8.0.0\
5
+ > `ignoreSpans`: requires `@sentry/react` ≥10.2.0\
6
+ > `enableAsyncRouteHandlers` + `lazyRouteManifest`: requires `@sentry/react` ≥10.39.0\
7
+ > `enableLongAnimationFrame`: requires `@sentry/react` ≥8.18.0
8
+
9
+ ---
10
+
11
+ ## How Automatic Tracing Works
12
+
13
+ | What’s traced | Op | How |
14
+ | -------------------------------------- | ------------------------- | --------------------------------------------------------------- |
15
+ | Initial page load | `pageload` | `browserTracingIntegration()` reads `window.performance` timing |
16
+ | Client-side navigations | `navigation` | History API (pushState / replaceState) |
17
+ | `fetch()` requests | `http.client` | Patched automatically |
18
+ | `XMLHttpRequest` requests | `http.client` | Patched automatically |
19
+ | Long Tasks (main-thread blocks > 50ms) | `ui.long-task` | `PerformanceLongTaskTiming` observer |
20
+ | Long Animation Frames (≥8.18.0) | `ui.long-animation-frame` | `PerformanceLongAnimationFrameTiming` observer |
21
+ | INP interactions | `ui.interaction` | `PerformanceEventTiming` observer, emitted on page hide |
22
+
23
+ ---
24
+
25
+ ## Core Setup
26
+
27
+ ```typescript
28
+ // src/instrument.ts (imported FIRST in main.tsx / index.tsx)
29
+ import * as Sentry from "@sentry/react";
30
+
31
+ Sentry.init({
32
+ dsn: import.meta.env.VITE_SENTRY_DSN,
33
+ environment: import.meta.env.MODE,
34
+
35
+ integrations: [Sentry.browserTracingIntegration()],
36
+
37
+ // Tracing sample rates
38
+ tracesSampleRate: 1.0, // 100% in dev; lower to 0.1–0.2 in production
39
+
40
+ // Which outgoing requests get sentry-trace + baggage headers
41
+ tracePropagationTargets: ["localhost", /^https:\/\/api\.yourapp\.com/],
42
+ });
43
+ ```
44
+
45
+ > **To disable tracing entirely:** omit both `tracesSampleRate` and `tracesSampler`.
46
+ > Setting `tracesSampleRate: 0` is **not** the same — the integration still runs, it
47
+ > just doesn’t send data.
48
+
49
+ ---
50
+
51
+ ## `browserTracingIntegration` — All Options
52
+
53
+ ```typescript
54
+ Sentry.browserTracingIntegration({/* option: default */});
55
+ ```
56
+
57
+ ### Page Load & Navigation
58
+
59
+ | Option | Type | Default | Description |
60
+ | ---------------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
61
+ | `instrumentPageLoad` | `boolean` | `true` | Create a `pageload` span on initial load. Disable when you want to name the span yourself via `startBrowserTracingPageLoadSpan`. |
62
+ | `instrumentNavigation` | `boolean` | `true` | Create `navigation` spans on History API changes. |
63
+
64
+ ### Span Lifecycle / Timing
65
+
66
+ | Option | Type | Default | Description |
67
+ | -------------------- | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
68
+ | `idleTimeout` | `number` (ms) | `1000` | How long to wait after the last child span finishes before closing the root span. The root takes the last child’s end time as its own end time. |
69
+ | `finalTimeout` | `number` (ms) | `30000` | Hard cap on how long a pageload/navigation span can live. Prevents runaway open spans. |
70
+ | `childSpanTimeout` | `number` (ms) | `15000` | If a child span hasn’t finished within this time, the root span finishes anyway. |
71
+ | `markBackgroundSpan` | `boolean` | `true` | When the tab goes to the background, mark the active span as `cancelled` and close it. |
72
+
73
+ ### HTTP Request Spans
74
+
75
+ | Option | Type | Default | Description |
76
+ | ---------------------------- | ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
77
+ | `traceFetch` | `boolean` | `true` | Auto-create child spans for `fetch()` calls. |
78
+ | `traceXHR` | `boolean` | `true` | Auto-create child spans for `XMLHttpRequest` calls. |
79
+ | `enableHTTPTimings` | `boolean` | `true` | Enrich HTTP spans with Resource Timing API data: DNS lookup, TLS handshake, connection, TTFB, download time. |
80
+ | `shouldCreateSpanForRequest` | `(url: string) => boolean` | — | Return `false` to skip creating a span for a specific URL. |
81
+ | `onRequestSpanStart` | `(span, requestInfo) => void` | — | Fires when a fetch/XHR span starts. Add custom attributes based on headers or URL. |
82
+
83
+ ### Performance Observations
84
+
85
+ | Option | Type | Default | Description |
86
+ | -------------------------- | --------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
87
+ | `enableLongTask` | `boolean` | `true` | Capture spans for Long Tasks — main-thread blocks > 50ms. |
88
+ | `enableLongAnimationFrame` | `boolean` | `true` | Capture Long Animation Frames (LoAF). Supersedes Long Tasks for most use cases. SDK ≥8.18.0. |
89
+ | `enableInp` | `boolean` | `true` (SDK 8.x+) | Auto-capture INP events as standalone spans. In SDK 7.x, defaults to `false` and must be opted in. |
90
+ | `interactionsSampleRate` | `number` | `1.0` | Applied **on top of** `tracesSampleRate` for INP spans. `interactionsSampleRate: 0.5` + `tracesSampleRate: 0.1` = **5%** of interactions captured. |
91
+
92
+ ### Span Naming
93
+
94
+ | Option | Type | Default | Description |
95
+ | ----------------- | ------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
96
+ | `beforeStartSpan` | `(context: StartSpanOptions) => StartSpanOptions` | — | Called just before every pageload or navigation span is created. Mutate and return `context` to rename the span, change `op`, or add attributes. Primary use: parameterize URLs (`/users/123` → `/users/<id>`). |
97
+
98
+ ```typescript
99
+ browserTracingIntegration({
100
+ beforeStartSpan: (context) => ({
101
+ ...context,
102
+ name: location.pathname
103
+ .replace(/\/[a-f0-9]{8,}/g, "/<hash>") // strip hashes/UUIDs
104
+ .replace(/\/\d+/g, "/<id>"), // strip numeric IDs
105
+ }),
106
+ });
107
+ ```
108
+
109
+ ### Trace Linking
110
+
111
+ | Option | Type | Default | Description |
112
+ | ------------------------ | ------------------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- |
113
+ | `linkPreviousTrace` | `'in-memory' \| 'session-storage' \| false` | `'in-memory'` | How a new pageload links back to the previous trace. `'session-storage'` persists across hard reloads. `false` disables linking. |
114
+ | `enableReportPageLoaded` | `boolean` | `false` | Enables `Sentry.reportPageLoaded()` for manually signalling page load completion in complex hydration scenarios. |
115
+
116
+ ### Span Filtering
117
+
118
+ | Option | Type | Default | Description |
119
+ | --------------------------- | ------------------------- | ------- | --------------------------------------------------------------------------------------------------- |
120
+ | `ignoreResourceSpans` | `string[]` | `[]` | Skip resource spans by `op` prefix. Example: `["resource.css", "resource.script", "resource.img"]`. |
121
+ | `ignorePerformanceApiSpans` | `Array<string \| RegExp>` | `[]` | Skip spans created from `performance.mark()`/`performance.measure()` matching these names. |
122
+
123
+ ### Full Example With All Common Options
124
+
125
+ ```typescript
126
+ import * as Sentry from "@sentry/react";
127
+
128
+ Sentry.init({
129
+ dsn: import.meta.env.VITE_SENTRY_DSN,
130
+ environment: import.meta.env.MODE,
131
+
132
+ integrations: [
133
+ Sentry.browserTracingIntegration({
134
+ // Lifecycle
135
+ idleTimeout: 1000,
136
+ finalTimeout: 30_000,
137
+ childSpanTimeout: 15_000,
138
+ markBackgroundSpan: true,
139
+
140
+ // HTTP spans
141
+ traceFetch: true,
142
+ traceXHR: true,
143
+ enableHTTPTimings: true,
144
+ shouldCreateSpanForRequest: (url) =>
145
+ !url.includes("/health") && !url.includes("/__webpack_hmr"),
146
+ onRequestSpanStart: (span, { headers }) => {
147
+ const rid = headers?.["x-request-id"];
148
+ if (rid) span.setAttribute("request.id", rid);
149
+ },
150
+
151
+ // Performance observations
152
+ enableLongTask: true,
153
+ enableLongAnimationFrame: true, // SDK ≥8.18.0
154
+ enableInp: true,
155
+ interactionsSampleRate: 1.0,
156
+
157
+ // Span naming
158
+ beforeStartSpan: (context) => ({
159
+ ...context,
160
+ name: context.name.replace(/\/\d+/g, "/<id>"),
161
+ }),
162
+
163
+ // Filtering
164
+ ignoreResourceSpans: ["resource.css"],
165
+
166
+ // Trace linking
167
+ linkPreviousTrace: "in-memory",
168
+ }),
169
+ ],
170
+
171
+ tracesSampleRate: 1.0,
172
+ tracePropagationTargets: ["localhost", /^https:\/\/api\.myapp\.com/],
173
+ });
174
+ ```
175
+
176
+ ---
177
+
178
+ ## What’s Auto-Instrumented
179
+
180
+ ### Page Load (`op: "pageload"`)
181
+
182
+ - Created on initial page render using `window.performance` timing API
183
+ - Contains Web Vitals: **LCP**, **CLS**, **FCP**, **TTFB**
184
+ - HTTP requests made during page load appear as child spans
185
+ - Long Tasks and Long Animation Frames appear as child spans
186
+
187
+ ### Navigation (`op: "navigation"`)
188
+
189
+ - Created on every client-side navigation via the History API
190
+ - Does **not** include Web Vitals (those are page-load only)
191
+ - HTTP requests during navigation appear as child spans
192
+
193
+ ### HTTP Spans (`op: "http.client"`)
194
+
195
+ - Automatic for both `fetch()` and `XMLHttpRequest`
196
+ - Captures: method, URL, HTTP status code, response size
197
+ - With `enableHTTPTimings`: DNS lookup time, TLS handshake, connection time, TTFB,
198
+ download time
199
+
200
+ ### Long Task Spans (`op: "ui.long-task"`)
201
+
202
+ - Created for any main-thread block > 50ms
203
+ - Helps identify JavaScript that blocks interactivity
204
+
205
+ ### Long Animation Frame Spans (`op: "ui.long-animation-frame"`)
206
+
207
+ - SDK 8.18.0+; based on the LoAF API
208
+ - Captures render-blocking work including style/layout recalculations
209
+ - More accurate than Long Tasks for measuring rendering bottlenecks
210
+
211
+ ### INP / Interaction Spans (`op: "ui.interaction"`)
212
+
213
+ - Standalone spans capturing Interaction to Next Paint
214
+ - Emitted on page hide (tab switch, navigation away)
215
+ - Attributes: `component`, `element`, `interaction_type`
216
+ - On by default in SDK 8.x+; opt-in (`enableInp: true`) in SDK 7.x
217
+
218
+ ---
219
+
220
+ ## Web Vitals
221
+
222
+ `browserTracingIntegration()` captures Core Web Vitals automatically and surfaces them
223
+ in the **Sentry Web Vitals** product module:
224
+
225
+ | Vital | What it measures | Good | Needs Improvement | Poor |
226
+ | ----------------------------------- | ------------------------------------------------------------------ | ------- | ----------------- | ------- |
227
+ | **LCP** — Largest Contentful Paint | Time for largest viewport element to render | ≤ 2.5s | ≤ 4s | > 4s |
228
+ | **INP** — Interaction to Next Paint | Time from user interaction to next paint (replaced FID March 2024) | ≤ 200ms | ≤ 500ms | > 500ms |
229
+ | **CLS** — Cumulative Layout Shift | Sum of unexpected layout shift scores | ≤ 0.1 | ≤ 0.25 | > 0.25 |
230
+ | **FCP** — First Contentful Paint | Time for first content to render | ≤ 1s | ≤ 3s | > 3s |
231
+ | **TTFB** — Time to First Byte | Time until browser receives first byte | ≤ 100ms | ≤ 200ms | > 200ms |
232
+ | **FID** — First Input Delay | _(Legacy — collected but replaced by INP)_ | ≤ 100ms | ≤ 300ms | > 300ms |
233
+
234
+ > **LCP and CLS timing note:** These keep changing after the pageload span ends.
235
+ > Sentry captures their final values via `visibilitychange` and page hide events.
236
+ > INP is similarly emitted as a standalone span on page hide.
237
+
238
+ **INP in SDK 7.x** (must opt in):
239
+
240
+ ```typescript
241
+ browserTracingIntegration({ enableInp: true });
242
+ ```
243
+
244
+ ---
245
+
246
+ ## React Router Integrations
247
+
248
+ All React Router integrations live in `@sentry/react`. The core mechanism: **replace**
249
+ `browserTracingIntegration()` with the router-specific variant.
250
+ Both cannot be used simultaneously.
251
+
252
+ > This section is for React Router non-framework/data/declarative usage.
253
+ > If the project uses React Router Framework mode with `@sentry/react-router`, use
254
+ > [`react-router-framework`](../react-router-framework/index.md).
255
+
256
+ ---
257
+
258
+ ### React Router v7 (Library Mode)
259
+
260
+ **Package:** `react-router` (v7)\
261
+ **Import source for hooks:** `"react-router"`
262
+
263
+ #### Method 1 — `createBrowserRouter` (Recommended)
264
+
265
+ ```typescript
266
+ // src/instrument.ts
267
+ import React from "react";
268
+ import {
269
+ createBrowserRouter,
270
+ createRoutesFromChildren,
271
+ matchRoutes,
272
+ useLocation,
273
+ useNavigationType,
274
+ } from "react-router";
275
+ import * as Sentry from "@sentry/react";
276
+
277
+ Sentry.init({
278
+ dsn: import.meta.env.VITE_SENTRY_DSN,
279
+ integrations: [
280
+ Sentry.reactRouterV7BrowserTracingIntegration({
281
+ useEffect: React.useEffect,
282
+ useLocation,
283
+ useNavigationType,
284
+ createRoutesFromChildren,
285
+ matchRoutes,
286
+ }),
287
+ ],
288
+ tracesSampleRate: 1.0,
289
+ tracePropagationTargets: ["localhost", /^https:\/\/api\.myapp\.com/],
290
+ });
291
+ ```
292
+
293
+ ```typescript
294
+ // src/router.ts
295
+ import { createBrowserRouter } from "react-router";
296
+ import * as Sentry from "@sentry/react";
297
+ import { RootLayout, RootErrorBoundary } from "./layouts";
298
+ import { HomePage, UsersPage, UserDetailPage, DashboardPage } from "./pages";
299
+
300
+ // Wrap createBrowserRouter with Sentry instrumentation
301
+ const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV7(createBrowserRouter);
302
+
303
+ export const router = sentryCreateBrowserRouter([
304
+ {
305
+ path: "/",
306
+ element: <RootLayout />,
307
+ errorElement: <RootErrorBoundary />, // see Error Boundary section below
308
+ children: [
309
+ { index: true, element: <HomePage /> },
310
+ { path: "users", element: <UsersPage /> },
311
+ { path: "users/:userId", element: <UserDetailPage /> },
312
+ { path: "dashboard", element: <DashboardPage />,
313
+ children: [
314
+ { path: "analytics", element: <AnalyticsPage /> },
315
+ ],
316
+ },
317
+ ],
318
+ },
319
+ ]);
320
+ ```
321
+
322
+ ```typescript
323
+ // src/main.tsx
324
+ import ReactDOM from "react-dom/client";
325
+ import { RouterProvider } from "react-router";
326
+ import "./instrument"; // ← MUST be first
327
+ import { router } from "./router";
328
+
329
+ ReactDOM.createRoot(document.getElementById("root")!).render(
330
+ <RouterProvider router={router} />
331
+ );
332
+ ```
333
+
334
+ **Lazy routes (SDK ≥10.39.0):** add `enableAsyncRouteHandlers` and declare all route
335
+ paths:
336
+
337
+ ```typescript
338
+ Sentry.reactRouterV7BrowserTracingIntegration({
339
+ useEffect: React.useEffect,
340
+ useLocation,
341
+ useNavigationType,
342
+ createRoutesFromChildren,
343
+ matchRoutes,
344
+ enableAsyncRouteHandlers: true,
345
+ lazyRouteManifest: [
346
+ "/",
347
+ "/users",
348
+ "/users/:userId",
349
+ "/users/:userId/settings",
350
+ "/dashboard",
351
+ "/dashboard/analytics",
352
+ ],
353
+ });
354
+ ```
355
+
356
+ **Other router factories:**
357
+
358
+ | Factory | Sentry wrapper |
359
+ | --------------------- | --------------------------------------------------- |
360
+ | `createBrowserRouter` | `Sentry.wrapCreateBrowserRouterV7` |
361
+ | `createMemoryRouter` | `Sentry.wrapCreateMemoryRouterV7` |
362
+ | `createHashRouter` | `Sentry.wrapCreateBrowserRouterV7` (works for both) |
363
+
364
+ #### Method 2 — `<Routes>` Component
365
+
366
+ ```typescript
367
+ import React from "react";
368
+ import ReactDOM from "react-dom/client";
369
+ import {
370
+ BrowserRouter, Routes, Route,
371
+ createRoutesFromChildren, matchRoutes,
372
+ useLocation, useNavigationType,
373
+ } from "react-router";
374
+ import * as Sentry from "@sentry/react";
375
+
376
+ Sentry.init({
377
+ // ... same init as Method 1
378
+ });
379
+
380
+ // Wrap Routes ONCE at the top level — do NOT wrap nested <Routes>
381
+ const SentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes);
382
+
383
+ function App() {
384
+ return (
385
+ <BrowserRouter>
386
+ <SentryRoutes>
387
+ <Route path="/" element={<HomePage />} />
388
+ <Route path="/about" element={<AboutPage />} />
389
+ <Route path="/users/:userId" element={<UserDetailPage />} />
390
+ <Route path="*" element={<NotFoundPage />} />
391
+ </SentryRoutes>
392
+ </BrowserRouter>
393
+ );
394
+ }
395
+ ```
396
+
397
+ Also works with `MemoryRouter` and `HashRouter`.
398
+
399
+ #### Method 3 — `useRoutes` Hook
400
+
401
+ ```typescript
402
+ import { useRoutes, BrowserRouter } from "react-router";
403
+ import * as Sentry from "@sentry/react";
404
+
405
+ // MUST call wrapUseRoutesV7 OUTSIDE any React component
406
+ const useSentryRoutes = Sentry.wrapUseRoutesV7(useRoutes);
407
+
408
+ function App() {
409
+ return useSentryRoutes([
410
+ { path: "/", element: <HomePage /> },
411
+ { path: "/users/:userId", element: <UserDetailPage /> },
412
+ { path: "/dashboard", element: <DashboardPage />,
413
+ children: [
414
+ { path: "analytics", element: <AnalyticsPage /> },
415
+ ],
416
+ },
417
+ ]);
418
+ }
419
+
420
+ ReactDOM.createRoot(document.getElementById("root")!).render(
421
+ <BrowserRouter><App /></BrowserRouter>
422
+ );
423
+ ```
424
+
425
+ #### Error Boundary (Required for Production Error Capture)
426
+
427
+ React Router v7’s default `errorElement` swallows errors silently.
428
+ You must capture them manually:
429
+
430
+ ```typescript
431
+ import { useRouteError } from "react-router";
432
+ import * as Sentry from "@sentry/react";
433
+
434
+ export function SentryRouteErrorBoundary() {
435
+ const error = useRouteError() as Error;
436
+
437
+ React.useEffect(() => {
438
+ if (error) Sentry.captureException(error);
439
+ }, [error]);
440
+
441
+ return (
442
+ <div role="alert">
443
+ <h1>Something went wrong</h1>
444
+ <p>{error?.message ?? "An unexpected error occurred."}</p>
445
+ </div>
446
+ );
447
+ }
448
+
449
+ // Apply as errorElement on your root route and any nested boundaries:
450
+ const router = sentryCreateBrowserRouter([
451
+ {
452
+ path: "/",
453
+ element: <RootLayout />,
454
+ errorElement: <SentryRouteErrorBoundary />,
455
+ children: [
456
+ {
457
+ path: "checkout",
458
+ element: <CheckoutPage />,
459
+ errorElement: <SentryRouteErrorBoundary />, // nested boundary
460
+ },
461
+ ],
462
+ },
463
+ ]);
464
+ ```
465
+
466
+ ---
467
+
468
+ ### React Router v6
469
+
470
+ **Package:** `react-router-dom` (v6)\
471
+ **Import source for hooks:** `"react-router-dom"`
472
+
473
+ #### Method 1 — `createBrowserRouter` (Recommended for v6.4+)
474
+
475
+ ```typescript
476
+ import React from "react";
477
+ import {
478
+ createBrowserRouter,
479
+ createRoutesFromChildren,
480
+ matchRoutes,
481
+ useLocation,
482
+ useNavigationType,
483
+ } from "react-router-dom";
484
+ import * as Sentry from "@sentry/react";
485
+
486
+ Sentry.init({
487
+ dsn: import.meta.env.VITE_SENTRY_DSN,
488
+ integrations: [
489
+ Sentry.reactRouterV6BrowserTracingIntegration({
490
+ useEffect: React.useEffect,
491
+ useLocation,
492
+ useNavigationType,
493
+ createRoutesFromChildren,
494
+ matchRoutes,
495
+ }),
496
+ ],
497
+ tracesSampleRate: 1.0,
498
+ });
499
+
500
+ // Wrap createBrowserRouter
501
+ const sentryCreateBrowserRouter =
502
+ Sentry.wrapCreateBrowserRouterV6(createBrowserRouter);
503
+
504
+ export const router = sentryCreateBrowserRouter([
505
+ {
506
+ path: "/",
507
+ element: <Root />,
508
+ children: [
509
+ { index: true, element: <HomePage /> },
510
+ { path: "users/:userId", element: <UserDetailPage /> },
511
+ { path: "settings", element: <SettingsPage /> },
512
+ ],
513
+ },
514
+ ]);
515
+ ```
516
+
517
+ **Other router factories (SDK ≥8.50.0):**
518
+
519
+ | Factory | Sentry wrapper |
520
+ | --------------------- | ---------------------------------- |
521
+ | `createBrowserRouter` | `Sentry.wrapCreateBrowserRouterV6` |
522
+ | `createMemoryRouter` | `Sentry.wrapCreateMemoryRouterV6` |
523
+
524
+ #### Method 2 — `<Routes>` Component
525
+
526
+ ```typescript
527
+ import {
528
+ BrowserRouter, Routes, Route,
529
+ createRoutesFromChildren, matchRoutes,
530
+ useLocation, useNavigationType,
531
+ } from "react-router-dom";
532
+ import * as Sentry from "@sentry/react";
533
+
534
+ Sentry.init({ /* ... same as above */ });
535
+
536
+ const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes);
537
+
538
+ function App() {
539
+ return (
540
+ <BrowserRouter>
541
+ <SentryRoutes>
542
+ <Route path="/" element={<HomePage />} />
543
+ <Route path="/users/:userId" element={<UserPage />} />
544
+ <Route path="*" element={<NotFoundPage />} />
545
+ </SentryRoutes>
546
+ </BrowserRouter>
547
+ );
548
+ }
549
+ ```
550
+
551
+ #### Method 3 — `useRoutes` Hook
552
+
553
+ ```typescript
554
+ import { useRoutes, BrowserRouter } from "react-router-dom";
555
+ import * as Sentry from "@sentry/react";
556
+
557
+ // Call OUTSIDE components
558
+ const useSentryRoutes = Sentry.wrapUseRoutesV6(useRoutes);
559
+
560
+ function App() {
561
+ return useSentryRoutes([
562
+ { path: "/", element: <Home /> },
563
+ { path: "/users/:userId", element: <User /> },
564
+ ]);
565
+ }
566
+ ```
567
+
568
+ ---
569
+
570
+ ### React Router v4 / v5
571
+
572
+ **Package:** `react-router-dom` (v4 or v5) + `history`
573
+
574
+ #### Method 1 — `withSentryRouting` HOC (Recommended)
575
+
576
+ ```typescript
577
+ import React from "react";
578
+ import ReactDOM from "react-dom";
579
+ import { Route, Router, Switch } from "react-router-dom";
580
+ import { createBrowserHistory } from "history";
581
+ import * as Sentry from "@sentry/react";
582
+
583
+ // 1. Create a history instance
584
+ const history = createBrowserHistory();
585
+
586
+ // 2. Init with reactRouterV5BrowserTracingIntegration
587
+ Sentry.init({
588
+ dsn: "...",
589
+ integrations: [
590
+ Sentry.reactRouterV5BrowserTracingIntegration({ history }),
591
+ ],
592
+ tracesSampleRate: 1.0,
593
+ });
594
+
595
+ // 3. Wrap Route with HOC — enables parameterized transaction names
596
+ const SentryRoute = Sentry.withSentryRouting(Route);
597
+
598
+ // 4. Use SentryRoute everywhere instead of Route
599
+ // ORDER MATTERS — most specific paths first (decreasing specificity)
600
+ function App() {
601
+ return (
602
+ <Router history={history}>
603
+ <Switch>
604
+ <SentryRoute path="/users/:userId/settings" component={UserSettingsPage} />
605
+ <SentryRoute path="/users/:userId" component={UserPage} />
606
+ <SentryRoute path="/users" component={UsersPage} />
607
+ <SentryRoute path="/" component={HomePage} />
608
+ </Switch>
609
+ </Router>
610
+ );
611
+ }
612
+
613
+ ReactDOM.render(<App />, document.getElementById("root"));
614
+ ```
615
+
616
+ #### Method 2 — Static Route Config (no HOC)
617
+
618
+ ```typescript
619
+ import { matchPath } from "react-router-dom";
620
+ import { createBrowserHistory } from "history";
621
+ import * as Sentry from "@sentry/react";
622
+
623
+ const history = createBrowserHistory();
624
+
625
+ // Define all routes; most specific first
626
+ const routes = [
627
+ { path: "/users/:userId/settings" },
628
+ { path: "/users/:userId" },
629
+ { path: "/users" },
630
+ { path: "/dashboard/analytics" },
631
+ { path: "/dashboard" },
632
+ { path: "/" },
633
+ ];
634
+
635
+ Sentry.init({
636
+ dsn: "...",
637
+ integrations: [
638
+ Sentry.reactRouterV5BrowserTracingIntegration({
639
+ history,
640
+ routes,
641
+ matchPath, // from react-router-dom
642
+ }),
643
+ ],
644
+ tracesSampleRate: 1.0,
645
+ });
646
+ ```
647
+
648
+ **React Router v4:** use `Sentry.reactRouterV4BrowserTracingIntegration` — the API is
649
+ identical to v5.
650
+
651
+ ---
652
+
653
+ ### TanStack Router
654
+
655
+ **Requires:** `@tanstack/react-router` ≥1.64.0
656
+
657
+ ```typescript
658
+ // src/main.tsx
659
+ import * as Sentry from "@sentry/react";
660
+ import { createRouter, RouterProvider } from "@tanstack/react-router";
661
+ import { routeTree } from "./routeTree.gen"; // generated by TanStack Router
662
+
663
+ // 1. Create the router first
664
+ const router = createRouter({
665
+ routeTree,
666
+ defaultPreload: "intent",
667
+ });
668
+
669
+ // 2. Init Sentry, passing the router instance
670
+ Sentry.init({
671
+ dsn: import.meta.env.VITE_SENTRY_DSN,
672
+ integrations: [
673
+ Sentry.tanstackRouterBrowserTracingIntegration(router),
674
+ ],
675
+ tracesSampleRate: 1.0,
676
+ tracePropagationTargets: ["localhost", /^https:\/\/api\.myapp\.com/],
677
+ });
678
+
679
+ // 3. Render
680
+ ReactDOM.createRoot(document.getElementById("root")!).render(
681
+ <StrictMode>
682
+ <Sentry.ErrorBoundary fallback={<p>An error has occurred</p>}>
683
+ <RouterProvider router={router} />
684
+ </Sentry.ErrorBoundary>
685
+ </StrictMode>
686
+ );
687
+ ```
688
+
689
+ **Key difference vs React Router:** `tanstackRouterBrowserTracingIntegration` takes the
690
+ router instance directly — no hooks (`useLocation`, `useNavigationType`) or helpers
691
+ (`createRoutesFromChildren`, `matchRoutes`) are needed.
692
+ TanStack Router exposes its route definitions directly to the SDK.
693
+
694
+ ---
695
+
696
+ ### How Route Names Are Parameterized
697
+
698
+ All router integrations extract parameterized route patterns instead of literal URLs:
699
+
700
+ | Actual URL | Transaction Name |
701
+ | --------------------------- | ------------------------ |
702
+ | `/users/42` | `/users/:userId` |
703
+ | `/orders/abc-123/items` | `/orders/:orderId/items` |
704
+ | `/posts/2024/my-first-post` | `/posts/:year/:slug` |
705
+
706
+ This grouping is essential for meaningful performance data — without it, every user
707
+ generates a unique transaction name and nothing can be aggregated.
708
+
709
+ ---
710
+
711
+ ### Router Integration Quick-Reference
712
+
713
+ ```
714
+ Are you using React Router?
715
+ ├─ Framework mode (`@sentry/react-router`) ─► use the react-router-framework reference
716
+
717
+ ├─ v7 (react-router package) ──────► reactRouterV7BrowserTracingIntegration
718
+ │ ├─ createBrowserRouter? ──────► wrapCreateBrowserRouterV7(createBrowserRouter)
719
+ │ ├─ createMemoryRouter? ───────► wrapCreateMemoryRouterV7(createMemoryRouter)
720
+ │ ├─ <Routes> component? ───────► withSentryReactRouterV7Routing(Routes)
721
+ │ └─ useRoutes hook? ────────────► wrapUseRoutesV7(useRoutes)
722
+
723
+ ├─ v6 (react-router-dom) ──────────► reactRouterV6BrowserTracingIntegration
724
+ │ ├─ createBrowserRouter? ──────► wrapCreateBrowserRouterV6(createBrowserRouter)
725
+ │ ├─ createMemoryRouter? ───────► wrapCreateMemoryRouterV6(createMemoryRouter) [≥8.50.0]
726
+ │ ├─ <Routes> component? ───────► withSentryReactRouterV6Routing(Routes)
727
+ │ └─ useRoutes hook? ────────────► wrapUseRoutesV6(useRoutes)
728
+
729
+ ├─ v4/v5 ───────────────────────────► reactRouterV5BrowserTracingIntegration({ history })
730
+ │ ├─ with static routes array ──► add { routes, matchPath }
731
+ │ └─ without static routes ─────► withSentryRouting(Route) HOC
732
+
733
+ └─ No router / unsupported router ──► browserTracingIntegration()
734
+ └─ custom router ──────────────► { instrumentPageLoad: false, instrumentNavigation: false }
735
+ + startBrowserTracingPageLoadSpan
736
+ + startBrowserTracingNavigationSpan
737
+
738
+ Are you using TanStack Router?
739
+ └─ Any version ≥1.64.0 ─────────────► tanstackRouterBrowserTracingIntegration(router)
740
+ ```
741
+
742
+ ---
743
+
744
+ ## Custom Spans
745
+
746
+ ### The Three Span APIs
747
+
748
+ #### `Sentry.startSpan()` — Active, Auto-Ending (Recommended)
749
+
750
+ Wraps a block of work.
751
+ The span is active (collects children) and automatically ends when the callback returns
752
+ or resolves:
753
+
754
+ ```typescript
755
+ // Asynchronous
756
+ const data = await Sentry.startSpan(
757
+ {
758
+ name: "fetchUserProfile",
759
+ op: "http.client",
760
+ attributes: {
761
+ "user.id": userId,
762
+ "cache.hit": false,
763
+ },
764
+ },
765
+ async () => {
766
+ const res = await fetch(`/api/users/${userId}`);
767
+ return res.json();
768
+ },
769
+ );
770
+
771
+ // Synchronous
772
+ const result = Sentry.startSpan({ name: "computeRecommendations", op: "function" }, () =>
773
+ expensiveComputation(),
774
+ );
775
+
776
+ // Thrown errors are captured and the span is marked as error automatically
777
+ ```
778
+
779
+ #### `Sentry.startSpanManual()` — Active, Manual End
780
+
781
+ Use when the span lifetime cannot be enclosed in a single callback — e.g., middleware
782
+ that calls `next()`:
783
+
784
+ ```typescript
785
+ function authMiddleware(req: Request, res: Response, next: NextFunction) {
786
+ return Sentry.startSpanManual({ name: "auth.verify", op: "middleware" }, (span) => {
787
+ // span is active inside this callback only
788
+ res.once("finish", () => {
789
+ span.setStatus({ code: res.statusCode < 400 ? 1 : 2 });
790
+ span.end(); // ← REQUIRED — will not end automatically
791
+ });
792
+ return next();
793
+ });
794
+ }
795
+ ```
796
+
797
+ #### `Sentry.startInactiveSpan()` — Not Active, Manual End
798
+
799
+ For spans that cross event boundaries and should **not** automatically collect children
800
+ as parent:
801
+
802
+ ```typescript
803
+ let checkoutSpan: Sentry.Span | undefined;
804
+
805
+ // On flow start
806
+ document.getElementById("checkout-btn")!.addEventListener("click", () => {
807
+ checkoutSpan = Sentry.startInactiveSpan({
808
+ name: "checkout-flow",
809
+ op: "ui.flow",
810
+ });
811
+ });
812
+
813
+ // On flow end (later, in a different event handler)
814
+ document.getElementById("confirm-btn")!.addEventListener("click", () => {
815
+ checkoutSpan?.setAttribute("payment.method", "stripe");
816
+ checkoutSpan?.setStatus({ code: 1 });
817
+ checkoutSpan?.end(); // ← REQUIRED
818
+ });
819
+ ```
820
+
821
+ Explicit parent-child wiring with inactive spans:
822
+
823
+ ```typescript
824
+ const parentSpan = Sentry.startInactiveSpan({ name: "checkout-flow" });
825
+
826
+ const childA = Sentry.startInactiveSpan({
827
+ name: "validate-cart",
828
+ op: "function",
829
+ parentSpan, // ← explicit parent reference
830
+ });
831
+ await validateCart();
832
+ childA.end();
833
+
834
+ const childB = Sentry.startInactiveSpan({
835
+ name: "process-payment",
836
+ op: "function",
837
+ parentSpan,
838
+ });
839
+ await processPayment();
840
+ childB.end();
841
+
842
+ parentSpan.end();
843
+ ```
844
+
845
+ ---
846
+
847
+ ### Span Options Reference
848
+
849
+ ```typescript
850
+ interface StartSpanOptions {
851
+ name: string; // Required — label shown in the UI
852
+ op?: string; // Operation category (see table below)
853
+ startTime?: number; // Unix timestamp in seconds (can be float)
854
+ attributes?: Record<string, string | number | boolean | string[] | number[] | boolean[]>;
855
+ parentSpan?: Span; // Override default parent (mainly for startInactiveSpan)
856
+ onlyIfParent?: boolean; // Drop this span if there is no currently active parent
857
+ forceTransaction?: boolean; // Force span to appear as a root transaction in the UI
858
+ }
859
+ ```
860
+
861
+ **Common `op` values:**
862
+
863
+ | `op` | When to use |
864
+ | ------------------------- | ------------------------------------- |
865
+ | `http.client` | Outgoing HTTP requests |
866
+ | `db.query` | Database queries |
867
+ | `ui.render` | React component render work |
868
+ | `ui.load` | Async data loading for a page/view |
869
+ | `ui.click` | User click event handling |
870
+ | `ui.flow` | Multi-step UI flow (checkout, wizard) |
871
+ | `function` | General JS function calls |
872
+ | `task` | Background/scheduled work |
873
+ | `cache.get` / `cache.set` | Cache reads/writes |
874
+ | `middleware` | Express/Koa/Fastify middleware |
875
+
876
+ ---
877
+
878
+ ### Enriching Spans
879
+
880
+ ```typescript
881
+ const span = Sentry.getActiveSpan();
882
+
883
+ if (span) {
884
+ // Single attribute
885
+ span.setAttribute("db.table", "users");
886
+ span.setAttribute("db.rows_affected", 5);
887
+
888
+ // Multiple attributes at once
889
+ span.setAttributes({
890
+ "http.method": "POST",
891
+ "http.status_code": 201,
892
+ "user.tier": "premium",
893
+ });
894
+
895
+ // Status codes: 0=unset, 1=ok, 2=error
896
+ span.setStatus({ code: 1 });
897
+ span.setStatus({ code: 2, message: "Upstream timeout" });
898
+
899
+ // HTTP-specific shorthand
900
+ span.setHttpStatus(404); // sets code=2, message="Not Found"
901
+ span.setHttpStatus(200); // sets code=1
902
+
903
+ // Rename at runtime
904
+ span.updateName("GET /users/:id");
905
+
906
+ // End with explicit timestamp (seconds since epoch)
907
+ span.end(Date.now() / 1000);
908
+ }
909
+ ```
910
+
911
+ ---
912
+
913
+ ### Nesting Spans
914
+
915
+ Children nest automatically under the currently active span:
916
+
917
+ ```typescript
918
+ await Sentry.startSpan({ name: "loadDashboard", op: "ui.load" }, async () => {
919
+ // These are children of "loadDashboard"
920
+ const [user, posts] = await Promise.all([
921
+ Sentry.startSpan({ name: "fetchUser", op: "http.client" }, () =>
922
+ fetch("/api/user").then((r) => r.json()),
923
+ ),
924
+ Sentry.startSpan({ name: "fetchPosts", op: "http.client" }, () =>
925
+ fetch("/api/posts").then((r) => r.json()),
926
+ ),
927
+ ]);
928
+
929
+ // Sequential child — still nested under "loadDashboard"
930
+ await Sentry.startSpan({ name: "renderDashboard", op: "ui.render" }, async () => {
931
+ await renderContent(user, posts);
932
+ });
933
+ });
934
+ ```
935
+
936
+ ### `forceTransaction` — Standalone Root Span
937
+
938
+ Forces a span to appear as its own root transaction in the Sentry UI, independent of any
939
+ active parent. Useful for background workers, Web Workers, or queue processors:
940
+
941
+ ```typescript
942
+ Sentry.startSpan({ name: "processEmailQueue", op: "task", forceTransaction: true }, async () => {
943
+ const batch = await queue.take(50);
944
+ await processBatch(batch);
945
+ });
946
+ ```
947
+
948
+ ### Browser Flat Span Hierarchy
949
+
950
+ In browsers, all child spans are attached **flat** to the root span (not nested under
951
+ intermediate parents).
952
+ This prevents incorrect parent-child attribution in parallel async flows.
953
+
954
+ To opt into true nesting (use with care):
955
+
956
+ ```typescript
957
+ Sentry.init({
958
+ // ...
959
+ parentSpanIsAlwaysRootSpan: false,
960
+ });
961
+ ```
962
+
963
+ ---
964
+
965
+ ## Distributed Tracing
966
+
967
+ Distributed tracing connects a browser page load to all backend API calls it triggers,
968
+ creating a single end-to-end waterfall.
969
+
970
+ ### The Two Headers
971
+
972
+ | Header | Format | Purpose |
973
+ | -------------- | ------------------------------------------ | ------------------------------------ |
974
+ | `sentry-trace` | `{traceId}-{spanId}-{sampled}` | Carries trace context |
975
+ | `baggage` | W3C Baggage format with `sentry-*` entries | Carries sampling decision + metadata |
976
+
977
+ Both headers are automatically injected into `fetch()` and `XMLHttpRequest` for URLs
978
+ matching `tracePropagationTargets`.
979
+
980
+ ### `tracePropagationTargets`
981
+
982
+ ```typescript
983
+ Sentry.init({
984
+ tracePropagationTargets: [
985
+ // String = substring match against full URL
986
+ "localhost",
987
+ "api.myapp.com",
988
+
989
+ // RegExp = tested against full URL
990
+ /^https:\/\/api\.myapp\.com\//,
991
+ /^\/api\//, // same-origin relative paths
992
+
993
+ // Multiple backends
994
+ "https://auth.myapp.com",
995
+ "https://payments.myapp.com",
996
+ ],
997
+ });
998
+ ```
999
+
1000
+ **Defaults:** Same-origin requests get headers automatically.
1001
+ Cross-origin requests need explicit entries.
1002
+
1003
+ **Disable completely:**
1004
+
1005
+ ```typescript
1006
+ tracePropagationTargets: []; // no distributed tracing headers on any requests
1007
+ ```
1008
+
1009
+ ### CORS Requirements
1010
+
1011
+ Your backend APIs **must** allowlist these headers:
1012
+
1013
+ ```
1014
+ Access-Control-Allow-Headers: sentry-trace, baggage
1015
+ ```
1016
+
1017
+ Express example:
1018
+
1019
+ ```javascript
1020
+ app.use((_req, res, next) => {
1021
+ res.setHeader(
1022
+ "Access-Control-Allow-Headers",
1023
+ "Content-Type, Authorization, sentry-trace, baggage",
1024
+ );
1025
+ next();
1026
+ });
1027
+ ```
1028
+
1029
+ Without this, preflight requests fail and browsers suppress the headers.
1030
+
1031
+ ### SSR / Meta Tag Approach
1032
+
1033
+ When your HTML is server-rendered, emit Sentry trace context into `<meta>` tags.
1034
+ `browserTracingIntegration` reads them on init and attaches the pageload span to the
1035
+ server’s trace — the full request becomes one continuous trace.
1036
+
1037
+ Server (Node.js/Express):
1038
+
1039
+ ```typescript
1040
+ import * as Sentry from "@sentry/node";
1041
+
1042
+ app.get("/", (_req, res) => {
1043
+ const traceData = Sentry.getTraceData();
1044
+ // { "sentry-trace": "...", baggage: "..." }
1045
+ res.render("index", {
1046
+ sentryTrace: traceData["sentry-trace"],
1047
+ sentryBaggage: traceData["baggage"],
1048
+ });
1049
+ });
1050
+ ```
1051
+
1052
+ HTML template (EJS/Handlebars/Jinja/etc.):
1053
+
1054
+ ```html
1055
+ <head>
1056
+ <meta name="sentry-trace" content="<%= sentryTrace %>" />
1057
+ <meta name="baggage" content="<%= sentryBaggage %>" />
1058
+ </head>
1059
+ ```
1060
+
1061
+ The browser SDK reads these tags automatically — no extra client config needed.
1062
+
1063
+ ### Manual Propagation (WebSockets, Custom Channels)
1064
+
1065
+ For protocols that don’t support HTTP headers:
1066
+
1067
+ ```typescript
1068
+ // Browser (sender)
1069
+ const traceData = Sentry.getTraceData();
1070
+
1071
+ socket.send(
1072
+ JSON.stringify({
1073
+ type: "rpc.updateProfile",
1074
+ payload: { name: "Alice" },
1075
+ _sentry: {
1076
+ trace: traceData["sentry-trace"],
1077
+ baggage: traceData["baggage"],
1078
+ },
1079
+ }),
1080
+ );
1081
+ ```
1082
+
1083
+ ```typescript
1084
+ // Node.js server (receiver)
1085
+ import * as Sentry from "@sentry/node";
1086
+ import { propagation, context } from "@opentelemetry/api";
1087
+
1088
+ socket.on("message", (raw) => {
1089
+ const msg = JSON.parse(raw);
1090
+ const ctx = propagation.extract(context.active(), {
1091
+ "sentry-trace": msg._sentry.trace,
1092
+ baggage: msg._sentry.baggage,
1093
+ });
1094
+ context.with(ctx, () => {
1095
+ Sentry.startSpan({ name: "ws.updateProfile" }, () => handleMessage(msg));
1096
+ });
1097
+ });
1098
+ ```
1099
+
1100
+ ### W3C `traceparent` Compatibility (SDK ≥10.10.0)
1101
+
1102
+ Add the W3C `traceparent` header alongside `sentry-trace` for OpenTelemetry-native
1103
+ backends:
1104
+
1105
+ ```typescript
1106
+ Sentry.init({
1107
+ propagateTraceparent: true,
1108
+ });
1109
+ ```
1110
+
1111
+ ---
1112
+
1113
+ ## Sampling
1114
+
1115
+ ### `tracesSampleRate` — Uniform Rate
1116
+
1117
+ ```typescript
1118
+ Sentry.init({
1119
+ tracesSampleRate: 1.0, // 100% — dev / staging / low-traffic
1120
+ // tracesSampleRate: 0.2, // 20% — light production
1121
+ // tracesSampleRate: 0.05, // 5% — high-traffic production
1122
+ // tracesSampleRate: 0.01, // 1% — very high-traffic production
1123
+ });
1124
+ ```
1125
+
1126
+ ### `tracesSampler` — Dynamic Per-Transaction
1127
+
1128
+ `tracesSampler` replaces `tracesSampleRate` (when both are set, `tracesSampler` wins):
1129
+
1130
+ ```typescript
1131
+ Sentry.init({
1132
+ tracesSampler: ({ name, attributes, inheritOrSampleWith }) => {
1133
+ // Drop health checks and internal routes
1134
+ if (["/health", "/ping", "/readyz"].some((p) => name.includes(p))) return 0;
1135
+
1136
+ // Always capture critical flows
1137
+ if (name.startsWith("/checkout") || name.startsWith("/payment")) return 1.0;
1138
+
1139
+ // Sample admin routes at 50%
1140
+ if (name.startsWith("/admin")) return 0.5;
1141
+
1142
+ // High-volume search at 5%
1143
+ if (name.includes("/search")) return 0.05;
1144
+
1145
+ // For everything else: honor parent's decision, fall back to 10%
1146
+ return inheritOrSampleWith(0.1);
1147
+ },
1148
+ });
1149
+ ```
1150
+
1151
+ ### Full `samplingContext` Object
1152
+
1153
+ ```typescript
1154
+ interface SamplingContext {
1155
+ name: string; // Span/transaction name (e.g. "GET /users/:id")
1156
+ attributes?: SpanAttributes; // Initial span attributes: op, url, http.method, etc.
1157
+ parentSampled?: boolean; // Was the parent trace sampled? undefined = no parent
1158
+ parentSampleRate?: number; // What rate was used upstream?
1159
+ inheritOrSampleWith: (fallbackRate: number) => number;
1160
+ }
1161
+ ```
1162
+
1163
+ ### `inheritOrSampleWith` — Why It Matters
1164
+
1165
+ Use `inheritOrSampleWith(fallback)` instead of checking `parentSampled` directly.
1166
+ It enables:
1167
+
1168
+ - **Deterministic sampling:** the same rate decision is applied throughout the trace
1169
+ chain
1170
+ - **Accurate metric extrapolation:** Sentry’s performance metrics scale correctly only
1171
+ when consistent sample rates flow through all services
1172
+ - **Correct Sampled flag:** ensures the `sentry-sampled` value in downstream `baggage`
1173
+ matches the actual decision
1174
+
1175
+ ### Returning Boolean vs Number
1176
+
1177
+ ```typescript
1178
+ tracesSampler: ({ name }) => {
1179
+ if (name === "/critical") return true; // equivalent to 1.0
1180
+ if (name === "/noisy") return false; // equivalent to 0
1181
+ return 0.2;
1182
+ };
1183
+ ```
1184
+
1185
+ ### Sampling Guidelines by Traffic Level
1186
+
1187
+ | Daily transactions | Recommended `tracesSampleRate` |
1188
+ | ------------------ | ------------------------------------------------------------------------ |
1189
+ | < 10K | `1.0` — capture everything |
1190
+ | 10K–100K | `0.2` — 20% |
1191
+ | 100K–1M | `0.05` – `0.1` |
1192
+ | > 1M | `0.01` – `0.02` with `tracesSampler` for priority routes at higher rates |
1193
+
1194
+ ---
1195
+
1196
+ ## Span Filtering
1197
+
1198
+ ### `beforeSendTransaction` — Modify or Drop Whole Transactions
1199
+
1200
+ ```typescript
1201
+ Sentry.init({
1202
+ beforeSendTransaction(event) {
1203
+ // Drop internal/dev routes
1204
+ if (event.transaction?.startsWith("/__internal")) return null;
1205
+
1206
+ // Scrub PII from transaction names
1207
+ if (event.transaction) {
1208
+ event.transaction = event.transaction.replace(/\/users\/[^/]+/, "/users/<redacted>");
1209
+ }
1210
+
1211
+ // Add custom tags to every transaction
1212
+ event.tags = { ...event.tags, "app.build": BUILD_ID };
1213
+
1214
+ return event;
1215
+ },
1216
+ });
1217
+ ```
1218
+
1219
+ ### `ignoreTransactions` — Declarative Transaction Filtering
1220
+
1221
+ ```typescript
1222
+ Sentry.init({
1223
+ ignoreTransactions: [
1224
+ "/health", // string = substring match
1225
+ /^\/api\/internal/, // regex = full URL test
1226
+ "/__webpack_hmr",
1227
+ /\.(png|jpg|svg|ico|woff2)$/, // static assets
1228
+ ],
1229
+ });
1230
+ ```
1231
+
1232
+ ### `beforeSendSpan` — Modify Individual Spans
1233
+
1234
+ > `beforeSendSpan` **cannot drop spans** — it can only modify them.
1235
+ > To suppress spans, use `ignoreSpans` (SDK ≥10.2.0).
1236
+
1237
+ ```typescript
1238
+ Sentry.init({
1239
+ beforeSendSpan(span) {
1240
+ // Redact token from span descriptions
1241
+ if (span.op === "http.client" && span.description?.includes("/token")) {
1242
+ span.description = span.description.replace(/token=[^&]+/, "token=REDACTED");
1243
+ }
1244
+
1245
+ // Enrich all spans with deployment info
1246
+ span.data = {
1247
+ ...span.data,
1248
+ "deployment.region": import.meta.env.VITE_AWS_REGION ?? "unknown",
1249
+ };
1250
+
1251
+ return span; // must return span — never return null
1252
+ },
1253
+ });
1254
+ ```
1255
+
1256
+ ### `ignoreSpans` — Declarative Span Filtering (SDK ≥10.2.0)
1257
+
1258
+ ```typescript
1259
+ Sentry.init({
1260
+ ignoreSpans: [
1261
+ // String — matches against span name/description
1262
+ "font-load",
1263
+
1264
+ // Regex against span name
1265
+ /^performance\.mark\./,
1266
+
1267
+ // Object — filter by op only
1268
+ { op: "resource.script" },
1269
+ { op: "resource.img" },
1270
+ { op: "resource.css" },
1271
+
1272
+ // Object — filter by name and op together
1273
+ { name: "beacon", op: "http.client" },
1274
+
1275
+ // Object — name regex
1276
+ { name: /^(hotjar|analytics|gtag)/ },
1277
+
1278
+ // Object — filter by span attributes (SDK ≥10.6.0)
1279
+ // String attribute values use substring/RegExp matching; non-strings use strict equality
1280
+ {
1281
+ attributes: {
1282
+ "url.path": "/health", // substring match
1283
+ "http.response.status_code": 200, // strict equality
1284
+ },
1285
+ },
1286
+ ],
1287
+ });
1288
+ ```
1289
+
1290
+ > **Warning:** If the root span (the transaction itself) matches an `ignoreSpans` rule,
1291
+ > the **entire local trace is dropped**.
1292
+
1293
+ ---
1294
+
1295
+ ## Custom Routing (Manual Spans)
1296
+
1297
+ For unsupported or custom routers, disable auto page spans and drive them yourself:
1298
+
1299
+ ```typescript
1300
+ import * as Sentry from "@sentry/react";
1301
+ import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from "@sentry/react";
1302
+
1303
+ const client = Sentry.init({
1304
+ dsn: "...",
1305
+ integrations: [
1306
+ Sentry.browserTracingIntegration({
1307
+ instrumentPageLoad: false, // handled manually
1308
+ instrumentNavigation: false, // handled manually
1309
+ }),
1310
+ ],
1311
+ tracesSampleRate: 1.0,
1312
+ })!;
1313
+
1314
+ // Initial page load — name with URL until route is matched
1315
+ let pageLoadSpan = Sentry.startBrowserTracingPageLoadSpan(client, {
1316
+ name: window.location.pathname,
1317
+ attributes: {
1318
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url", // start with "url" source
1319
+ },
1320
+ });
1321
+
1322
+ // Once the router resolves the matched route
1323
+ myCustomRouter.on("routeResolved", (route) => {
1324
+ if (pageLoadSpan) {
1325
+ // Upgrade the pageload span's name to the parameterized pattern
1326
+ pageLoadSpan.updateName(route.pattern); // e.g. "/users/:id"
1327
+ pageLoadSpan.setAttribute(
1328
+ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
1329
+ "route", // upgrade to "route" source
1330
+ );
1331
+ pageLoadSpan = undefined;
1332
+ } else {
1333
+ // Subsequent navigations
1334
+ Sentry.startBrowserTracingNavigationSpan(client, {
1335
+ op: "navigation",
1336
+ name: route.pattern,
1337
+ attributes: {
1338
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
1339
+ },
1340
+ });
1341
+ }
1342
+ });
1343
+ ```
1344
+
1345
+ Both functions create **idle spans** — they close automatically after `idleTimeout`ms of
1346
+ no new child activity, matching the behavior of automatic pageload/navigation spans.
1347
+
1348
+ ---
1349
+
1350
+ ## Full Import Reference
1351
+
1352
+ ```typescript
1353
+ import * as Sentry from "@sentry/react";
1354
+
1355
+ // ── Integrations ──────────────────────────────────────────────────────────
1356
+ Sentry.browserTracingIntegration(options);
1357
+ Sentry.reactRouterV7BrowserTracingIntegration(options);
1358
+ Sentry.reactRouterV6BrowserTracingIntegration(options);
1359
+ Sentry.reactRouterV5BrowserTracingIntegration(options);
1360
+ Sentry.reactRouterV4BrowserTracingIntegration(options);
1361
+ Sentry.tanstackRouterBrowserTracingIntegration(router);
1362
+
1363
+ // ── Router Wrappers — v7 ─────────────────────────────────────────────────
1364
+ Sentry.wrapCreateBrowserRouterV7(createBrowserRouter);
1365
+ Sentry.wrapCreateMemoryRouterV7(createMemoryRouter);
1366
+ Sentry.withSentryReactRouterV7Routing(Routes);
1367
+ Sentry.wrapUseRoutesV7(useRoutes);
1368
+
1369
+ // ── Router Wrappers — v6 ─────────────────────────────────────────────────
1370
+ Sentry.wrapCreateBrowserRouterV6(createBrowserRouter);
1371
+ Sentry.wrapCreateMemoryRouterV6(createMemoryRouter); // SDK ≥8.50.0
1372
+ Sentry.withSentryReactRouterV6Routing(Routes);
1373
+ Sentry.wrapUseRoutesV6(useRoutes);
1374
+
1375
+ // ── Router Wrappers — v5/v4 ──────────────────────────────────────────────
1376
+ Sentry.withSentryRouting(Route);
1377
+
1378
+ // ── Spans ────────────────────────────────────────────────────────────────
1379
+ Sentry.startSpan(options, callback);
1380
+ Sentry.startSpanManual(options, callback);
1381
+ Sentry.startInactiveSpan(options);
1382
+ Sentry.getActiveSpan();
1383
+
1384
+ // ── Custom Browser Tracing ───────────────────────────────────────────────
1385
+ Sentry.startBrowserTracingPageLoadSpan(client, options);
1386
+ Sentry.startBrowserTracingNavigationSpan(client, options);
1387
+
1388
+ // ── Distributed Tracing ──────────────────────────────────────────────────
1389
+ Sentry.getTraceData();
1390
+ // Returns: { "sentry-trace": string, baggage: string }
1391
+
1392
+ // ── Constants ────────────────────────────────────────────────────────────
1393
+ Sentry.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE; // "sentry.source"
1394
+ Sentry.SEMANTIC_ATTRIBUTE_SENTRY_OP; // "sentry.op"
1395
+ ```
1396
+
1397
+ ---
1398
+
1399
+ ## Troubleshooting
1400
+
1401
+ | Issue | Solution |
1402
+ | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
1403
+ | No transactions in Performance dashboard | Verify `tracesSampleRate` > 0; confirm `browserTracingIntegration()` (or router variant) is in `integrations` array |
1404
+ | Transaction names show raw URLs (`/users/42`) instead of patterns | Add router integration matching your router version; ensure it’s replacing, not supplementing, `browserTracingIntegration()` |
1405
+ | Transaction named `<unknown>` | Router integration is missing or misconfigured; check `useEffect`, `useLocation`, `useNavigationType` are all passed correctly |
1406
+ | Distributed trace not linking frontend → backend | Add backend URL to `tracePropagationTargets`; verify `Access-Control-Allow-Headers` includes `sentry-trace, baggage` |
1407
+ | SSR page load not linked to server trace | Inject `<meta name="sentry-trace">` and `<meta name="baggage">` tags from `Sentry.getTraceData()` in server-rendered HTML |
1408
+ | API requests missing `sentry-trace` header | Check CORS preflight — backend must allow `sentry-trace` and `baggage` headers |
1409
+ | INP spans not appearing | In SDK 7.x, enable explicitly: `browserTracingIntegration({ enableInp: true })` |
1410
+ | Web Vitals missing | Confirm `browserTracingIntegration()` is in client init; check browser support (INP requires Chromium 96+) |
1411
+ | Spans missing after async gap | Browser uses flat hierarchy; use `startInactiveSpan` with explicit `parentSpan` to enforce parent-child across async boundaries |
1412
+ | High transaction volume / cost | Use `tracesSampler` to return `0` for health checks and asset routes; lower default rate with `inheritOrSampleWith(0.05)` |
1413
+ | `beforeSendSpan` returning `null` breaks the SDK | `beforeSendSpan` must always return the span — use `ignoreSpans` to drop spans declaratively |
1414
+ | Lazy routes not tracked | Upgrade to SDK ≥10.39.0; add `enableAsyncRouteHandlers: true` and `lazyRouteManifest` with all route paths |
1415
+ | TanStack Router transactions missing | Ensure router is created **before** `Sentry.init()` is called and the router instance is passed to the integration |