@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,1100 @@
1
+ # Error Monitoring — Sentry .NET SDK
2
+
3
+ > Minimum SDK: `Sentry` ≥ 4.0.0 (NuGet)\
4
+ > ASP.NET Core integration: `Sentry.AspNetCore` ≥ 4.0.0\
5
+ > MAUI integration: `Sentry.Maui` ≥ 4.0.0\
6
+ > User feedback API: `Sentry` ≥ 4.0.0 (`CaptureFeedback`)
7
+
8
+ ---
9
+
10
+ ## Automatic vs Manual Error Capture
11
+
12
+ ### What Is Captured Automatically
13
+
14
+ | Error Type | Captured? | Mechanism |
15
+ | ------------------------------------ | --------- | ------------------------------------------------------ |
16
+ | Unhandled exceptions (all platforms) | ✅ Yes | `AppDomain.CurrentDomain.UnhandledException` |
17
+ | Unobserved Task exceptions | ✅ Yes | `TaskScheduler.UnobservedTaskException` |
18
+ | ASP.NET Core request errors | ✅ Yes | Sentry middleware |
19
+ | WPF Dispatcher unhandled exceptions | ✅ Yes | `Application.DispatcherUnhandledException` (with hook) |
20
+ | MAUI unhandled exceptions | ✅ Yes | Platform-specific native integrations |
21
+ | WinForms exceptions | ✅ Yes | Requires `SetUnhandledExceptionMode(ThrowException)` |
22
+ | Caught + swallowed `try/catch` | ❌ No | Must call `SentrySdk.CaptureException()` manually |
23
+ | Graceful error returns | ❌ No | Must call `SentrySdk.CaptureException()` manually |
24
+
25
+ ### The Core Rule
26
+
27
+ > **“If you catch an exception and don’t re-throw it, Sentry never sees it.”**
28
+
29
+ ```csharp
30
+ // ✅ Automatically captured — unhandled, bubbles up
31
+ throw new Exception("Unhandled");
32
+
33
+ // ✅ Automatically captured — re-thrown
34
+ try
35
+ {
36
+ await DoSomethingAsync();
37
+ }
38
+ catch (Exception ex)
39
+ {
40
+ throw; // re-throw preserves stack trace
41
+ }
42
+
43
+ // ❌ NOT captured — swallowed by graceful return
44
+ try
45
+ {
46
+ await DoSomethingAsync();
47
+ }
48
+ catch (Exception ex)
49
+ {
50
+ return Result.Failure("Operation failed"); // ← Sentry never sees this
51
+ }
52
+
53
+ // ✅ Manually captured
54
+ try
55
+ {
56
+ await DoSomethingAsync();
57
+ }
58
+ catch (Exception ex)
59
+ {
60
+ SentrySdk.CaptureException(ex);
61
+ return Result.Failure("Operation failed");
62
+ }
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Core Capture API
68
+
69
+ ### `SentrySdk.CaptureException`
70
+
71
+ ```csharp
72
+ // Basic — capture a caught exception
73
+ SentryId id = SentrySdk.CaptureException(exception);
74
+
75
+ // With inline scope enrichment — changes are isolated to this ONE event
76
+ SentryId id = SentrySdk.CaptureException(exception, scope =>
77
+ {
78
+ scope.SetTag("order.id", orderId.ToString());
79
+ scope.Level = SentryLevel.Fatal;
80
+ scope.User = new SentryUser { Id = userId };
81
+ });
82
+ ```
83
+
84
+ > **Key behavior:** The SDK clones the current scope before invoking the callback.
85
+ > Changes inside the callback apply only to that one event and do not affect subsequent
86
+ > events.
87
+
88
+ ### `SentrySdk.CaptureMessage`
89
+
90
+ ```csharp
91
+ // Default level is Info
92
+ SentrySdk.CaptureMessage("Something notable happened");
93
+
94
+ // With explicit severity
95
+ SentrySdk.CaptureMessage("Disk space critically low", SentryLevel.Warning);
96
+
97
+ // With scope enrichment
98
+ SentrySdk.CaptureMessage("Payment gateway timeout", scope =>
99
+ {
100
+ scope.SetTag("gateway", "stripe");
101
+ scope.Level = SentryLevel.Error;
102
+ }, SentryLevel.Error);
103
+ ```
104
+
105
+ **SentryLevel values:**
106
+
107
+ ```csharp
108
+ SentryLevel.Debug
109
+ SentryLevel.Info // default for CaptureMessage
110
+ SentryLevel.Warning
111
+ SentryLevel.Error
112
+ SentryLevel.Fatal
113
+ ```
114
+
115
+ ### `SentrySdk.CaptureEvent`
116
+
117
+ For full manual control over every field on the event:
118
+
119
+ ```csharp
120
+ var evt = new SentryEvent
121
+ {
122
+ Message = new SentryMessage { Message = "Custom structured event" },
123
+ Level = SentryLevel.Error
124
+ };
125
+ evt.SetTag("custom-tag", "value");
126
+ evt.Fingerprint = new[] { "custom-fingerprint" };
127
+ SentrySdk.CaptureEvent(evt);
128
+
129
+ // Construct from a caught exception
130
+ try { ... }
131
+ catch (Exception ex)
132
+ {
133
+ var evt = new SentryEvent(ex)
134
+ {
135
+ Level = SentryLevel.Fatal
136
+ };
137
+ SentrySdk.CaptureEvent(evt);
138
+ }
139
+ ```
140
+
141
+ ### All capture signatures
142
+
143
+ ```csharp
144
+ // CaptureException
145
+ SentryId SentrySdk.CaptureException(Exception exception)
146
+ SentryId SentrySdk.CaptureException(Exception exception, Action<Scope> configureScope)
147
+
148
+ // CaptureMessage
149
+ SentryId SentrySdk.CaptureMessage(string message, SentryLevel level = SentryLevel.Info)
150
+ SentryId SentrySdk.CaptureMessage(string message, Action<Scope> configureScope,
151
+ SentryLevel level = SentryLevel.Info)
152
+
153
+ // CaptureEvent
154
+ SentryId SentrySdk.CaptureEvent(SentryEvent evt, Scope? scope = null, SentryHint? hint = null)
155
+ SentryId SentrySdk.CaptureEvent(SentryEvent evt, Action<Scope> configureScope)
156
+ SentryId SentrySdk.CaptureEvent(SentryEvent evt, SentryHint? hint, Action<Scope> configureScope)
157
+
158
+ // Flush
159
+ void SentrySdk.Flush()
160
+ void SentrySdk.Flush(TimeSpan timeout)
161
+ Task SentrySdk.FlushAsync(TimeSpan timeout)
162
+
163
+ // Utility
164
+ bool SentrySdk.IsEnabled
165
+ SentryId SentrySdk.LastEventId
166
+ ```
167
+
168
+ ---
169
+
170
+ ## ASP.NET Core — Automatic & Manual Error Capture
171
+
172
+ ### Installation
173
+
174
+ ```shell
175
+ dotnet add package Sentry.AspNetCore
176
+ ```
177
+
178
+ ### Initialization in `Program.cs`
179
+
180
+ ```csharp
181
+ var builder = WebApplication.CreateBuilder(args);
182
+
183
+ builder.WebHost.UseSentry(options =>
184
+ {
185
+ options.Dsn = "https://...@sentry.io/...";
186
+ options.SendDefaultPii = true; // Include user IP, headers, auth
187
+ options.MaxRequestBodySize = RequestSize.Always;
188
+ options.TracesSampleRate = 1.0;
189
+ options.Debug = true;
190
+ });
191
+
192
+ var app = builder.Build();
193
+ app.Run();
194
+ ```
195
+
196
+ ### Via `appsettings.json` (no code required)
197
+
198
+ ```json
199
+ {
200
+ "Sentry": {
201
+ "Dsn": "https://...@sentry.io/...",
202
+ "SendDefaultPii": true,
203
+ "MaxRequestBodySize": "Always",
204
+ "MinimumBreadcrumbLevel": "Debug",
205
+ "MinimumEventLevel": "Warning",
206
+ "AttachStacktrace": true,
207
+ "Debug": true,
208
+ "TracesSampleRate": 1.0
209
+ }
210
+ }
211
+ ```
212
+
213
+ ### Via environment variables (double-underscore convention)
214
+
215
+ ```shell
216
+ Sentry__Dsn=https://...@sentry.io/...
217
+ Sentry__Debug=true
218
+ Sentry__TracesSampleRate=0.5
219
+ Sentry__SendDefaultPii=true
220
+ ```
221
+
222
+ ### What ASP.NET Core captures automatically
223
+
224
+ - All unhandled exceptions thrown from controllers and middleware → captured as Sentry
225
+ events
226
+ - HTTP request data (URL, method, headers, body if configured)
227
+ - User info from `IHttpContext` when `SendDefaultPii = true`
228
+ - Breadcrumbs and Events from `Microsoft.Extensions.Logging`
229
+ - Performance transactions for each HTTP request (when `TracesSampleRate > 0`)
230
+
231
+ ### Manual capture in a controller
232
+
233
+ ```csharp
234
+ [ApiController]
235
+ [Route("[controller]")]
236
+ public class OrderController : ControllerBase
237
+ {
238
+ [HttpPost]
239
+ public IActionResult CreateOrder(OrderRequest request)
240
+ {
241
+ try
242
+ {
243
+ _orderService.Create(request);
244
+ return Ok();
245
+ }
246
+ catch (PaymentDeclinedException ex)
247
+ {
248
+ SentrySdk.CaptureException(ex, scope =>
249
+ {
250
+ scope.SetTag("payment.gateway", request.PaymentGateway);
251
+ scope.SetExtra("order_amount", request.Amount);
252
+ });
253
+ return StatusCode(402, "Payment declined");
254
+ }
255
+ }
256
+ }
257
+ ```
258
+
259
+ ### Custom user factory (DI)
260
+
261
+ ```csharp
262
+ public class MyUserFactory : ISentryUserFactory
263
+ {
264
+ private readonly IHttpContextAccessor _accessor;
265
+
266
+ public MyUserFactory(IHttpContextAccessor accessor)
267
+ => _accessor = accessor;
268
+
269
+ public SentryUser? Create()
270
+ {
271
+ var user = _accessor.HttpContext?.User;
272
+ if (user?.Identity?.IsAuthenticated != true) return null;
273
+
274
+ return new SentryUser
275
+ {
276
+ Id = user.FindFirst(ClaimTypes.NameIdentifier)?.Value,
277
+ Email = user.FindFirst(ClaimTypes.Email)?.Value,
278
+ Username = user.Identity.Name
279
+ };
280
+ }
281
+ }
282
+
283
+ // Register in DI
284
+ services.AddSingleton<ISentryUserFactory, MyUserFactory>();
285
+ ```
286
+
287
+ ### ASP.NET Core-specific options
288
+
289
+ | Option | Type | Description |
290
+ | ------------------------ | ------------- | ----------------------------------------------------------- |
291
+ | `SendDefaultPii` | `bool` | Include request URL, headers, user IP, auth info |
292
+ | `MaxRequestBodySize` | `RequestSize` | `None`, `Small` (<4 KB), `Medium` (<10 KB), `Always` |
293
+ | `MinimumBreadcrumbLevel` | `LogLevel` | Min log level for breadcrumb capture from ILogger |
294
+ | `MinimumEventLevel` | `LogLevel` | Min log level to generate a Sentry error event from ILogger |
295
+ | `CaptureBlockingCalls` | `bool` | Detect `Task.Wait()` / `.Result` threadpool starvation |
296
+
297
+ ---
298
+
299
+ ## Scope Management
300
+
301
+ ### How Scopes Work in .NET
302
+
303
+ The **Hub** holds a stack of scopes.
304
+ When an event is captured the hub merges the topmost scope’s data into the event.
305
+ Scope storage mode is controlled by `IsGlobalModeEnabled`:
306
+
307
+ | `IsGlobalModeEnabled` | Storage | Use For |
308
+ | --------------------- | --------------- | ------------------------------------------ |
309
+ | `false` (default) | `AsyncLocal<T>` | Server apps — per-request isolation |
310
+ | `true` | Singleton | Desktop apps — shared scope across threads |
311
+
312
+ ### `ConfigureScope` — Persistent Changes
313
+
314
+ Modifies the current ambient scope permanently (until changed or scope is popped).
315
+ Use for session-level data:
316
+
317
+ ```csharp
318
+ SentrySdk.ConfigureScope(scope =>
319
+ {
320
+ scope.SetTag("tenant.id", tenantId);
321
+ scope.User = new SentryUser
322
+ {
323
+ Id = user.Id.ToString(),
324
+ Email = user.Email
325
+ };
326
+ scope.Level = SentryLevel.Warning;
327
+ scope.TransactionName = "UserCheckout";
328
+ });
329
+
330
+ // Async variant
331
+ await SentrySdk.ConfigureScopeAsync(async scope =>
332
+ {
333
+ var user = await _context.Users.FindAsync(userId);
334
+ scope.User = new SentryUser { Id = user.Id.ToString(), Email = user.Email };
335
+ });
336
+
337
+ // Allocation-free overload (avoids closure)
338
+ SentrySdk.ConfigureScope(
339
+ static (scope, tenantId) => scope.SetTag("tenant.id", tenantId),
340
+ currentTenantId);
341
+ ```
342
+
343
+ ### `PushScope` — Temporary Isolated Scope
344
+
345
+ Inherits parent scope data.
346
+ All changes inside the `using` block are discarded when disposed:
347
+
348
+ ```csharp
349
+ using (SentrySdk.PushScope())
350
+ {
351
+ SentrySdk.ConfigureScope(scope =>
352
+ {
353
+ scope.SetTag("operation", "bulk-import");
354
+ scope.User = new SentryUser { Id = userId };
355
+ });
356
+
357
+ SentrySdk.CaptureException(new Exception("Scoped error"));
358
+ } // scope is popped here — tags/user cleared
359
+ ```
360
+
361
+ ### Inline scope callback (preferred for single events)
362
+
363
+ The `configureScope` callback on capture methods is the preferred pattern for one-off
364
+ enrichment without needing a `using` block:
365
+
366
+ ```csharp
367
+ // Only this event carries the tag
368
+ SentrySdk.CaptureException(ex, scope =>
369
+ {
370
+ scope.SetTag("action", "checkout");
371
+ scope.Level = SentryLevel.Fatal;
372
+ });
373
+
374
+ // The next event is NOT affected
375
+ SentrySdk.CaptureException(otherEx);
376
+ ```
377
+
378
+ ### Clearing scope data
379
+
380
+ ```csharp
381
+ SentrySdk.ConfigureScope(scope =>
382
+ {
383
+ scope.User = new SentryUser(); // Clear user (e.g., on logout)
384
+ scope.Clear(); // Clear everything
385
+ scope.ClearBreadcrumbs();
386
+ scope.ClearAttachments();
387
+ });
388
+ ```
389
+
390
+ ### Scope decision guide
391
+
392
+ | Goal | API |
393
+ | ------------------------------------------ | ------------------------------------------- |
394
+ | Data on ALL events (app version, build ID) | `options.DefaultTags["key"] = "value"` |
395
+ | Session/request-level data | `SentrySdk.ConfigureScope(...)` |
396
+ | One specific event only | Inline `configureScope` callback on capture |
397
+ | Temporary sub-context (batch job, etc.) | `SentrySdk.PushScope()` + `using` |
398
+
399
+ ---
400
+
401
+ ## Context Enrichment
402
+
403
+ ### Tags (Indexed, Searchable)
404
+
405
+ Tags are **indexed** — use them for filtering, grouping, and alerting rules.
406
+
407
+ ```csharp
408
+ SentrySdk.ConfigureScope(scope =>
409
+ {
410
+ scope.SetTag("page.locale", "de-at");
411
+ scope.SetTag("user.plan", "enterprise");
412
+
413
+ // Set multiple at once
414
+ scope.SetTags(new Dictionary<string, string>
415
+ {
416
+ ["environment"] = "staging",
417
+ ["region"] = "us-east-1"
418
+ });
419
+
420
+ // Unset a tag
421
+ scope.UnsetTag("page.locale");
422
+ });
423
+
424
+ // Default tags for ALL events (set in options)
425
+ SentrySdk.Init(options =>
426
+ {
427
+ options.DefaultTags["app.version"] = "2.0.1";
428
+ options.DefaultTags["deployment.region"] = "us-east-1";
429
+ });
430
+ ```
431
+
432
+ **Tag constraints:** Keys ≤ 32 chars (`a-zA-Z`, `0-9`, `_`, `.`, `:`, `-`); values ≤ 200
433
+ chars, no newlines.
434
+
435
+ ### User
436
+
437
+ ```csharp
438
+ SentrySdk.ConfigureScope(scope =>
439
+ {
440
+ scope.User = new SentryUser
441
+ {
442
+ Id = "42",
443
+ Username = "john.doe",
444
+ Email = "john.doe@example.com",
445
+ IpAddress = "{{auto}}" // let Sentry infer from the connection
446
+ };
447
+
448
+ // Custom fields
449
+ scope.User.Other["account_type"] = "premium";
450
+ scope.User.Other["tenant_id"] = "acme-corp";
451
+ });
452
+
453
+ // Clear user on logout
454
+ SentrySdk.ConfigureScope(scope => scope.User = new SentryUser());
455
+ ```
456
+
457
+ **SentryUser properties:**
458
+
459
+ | Property | Type | Notes |
460
+ | ----------- | ----------------------------- | ---------------------------------------------------------------------------- |
461
+ | `Id` | `string?` | Internal identifier |
462
+ | `Username` | `string?` | Display label |
463
+ | `Email` | `string?` | Enables Gravatars and Sentry messaging |
464
+ | `IpAddress` | `string?` | `"{{auto}}"` to infer from connection; auto-set when `SendDefaultPii = true` |
465
+ | `Other` | `IDictionary<string, string>` | Arbitrary additional user data |
466
+
467
+ ### Breadcrumbs
468
+
469
+ **Manual:**
470
+
471
+ ```csharp
472
+ SentrySdk.AddBreadcrumb(
473
+ message: "User authenticated",
474
+ category: "auth",
475
+ level: BreadcrumbLevel.Info);
476
+
477
+ // With structured data
478
+ SentrySdk.AddBreadcrumb(
479
+ message: "User navigated to checkout",
480
+ category: "navigation",
481
+ type: "navigation",
482
+ data: new Dictionary<string, string>
483
+ {
484
+ ["from"] = "/cart",
485
+ ["to"] = "/checkout"
486
+ },
487
+ level: BreadcrumbLevel.Info);
488
+
489
+ // Using Breadcrumb object
490
+ var crumb = new Breadcrumb(
491
+ message: "Button clicked",
492
+ type: "user",
493
+ data: new Dictionary<string, string> { ["button_id"] = "submit" },
494
+ category: "ui.click",
495
+ level: BreadcrumbLevel.Info);
496
+ SentrySdk.AddBreadcrumb(crumb);
497
+ ```
498
+
499
+ **BreadcrumbLevel values:** `Debug`, `Info` (default), `Warning`, `Error`, `Fatal`
500
+
501
+ **Automatically captured breadcrumbs:**
502
+
503
+ | Source | Requires |
504
+ | ---------------- | ------------------------------------------------------ |
505
+ | HTTP requests | `SentryHttpMessageHandler` with `HttpClient` |
506
+ | Logs (Info+) | `Microsoft.Extensions.Logging`, Serilog, NLog, log4net |
507
+ | Database queries | EF6 or EF Core via DiagnosticSource |
508
+ | MAUI app events | Navigation, lifecycle, user interactions |
509
+
510
+ Max breadcrumbs: 100 (default).
511
+ Override with `options.MaxBreadcrumbs = 50`.
512
+
513
+ ### Custom Contexts (Structured, Non-Searchable)
514
+
515
+ ```csharp
516
+ SentrySdk.ConfigureScope(scope =>
517
+ {
518
+ scope.Contexts["character"] = new
519
+ {
520
+ Name = "Mighty Fighter",
521
+ Age = 19,
522
+ AttackType = "melee"
523
+ };
524
+
525
+ scope.Contexts["build"] = new
526
+ {
527
+ Version = "2.0.1",
528
+ Commit = "abc123",
529
+ Pipeline = "main-ci"
530
+ };
531
+ });
532
+ ```
533
+
534
+ > The key `"type"` is **reserved** — do not use it.
535
+ > Contexts are not searchable; use Tags for searchable data.
536
+
537
+ ### Tags vs Contexts vs Extra
538
+
539
+ | Feature | Searchable? | Indexed? | Best For |
540
+ | ------------------ | ------------ | -------- | -------------------------------------- |
541
+ | **Tags** | ✅ Yes | ✅ Yes | Filtering, grouping, alerting |
542
+ | **Contexts** | ❌ No | ❌ No | Structured debug info (nested objects) |
543
+ | **Extra** (legacy) | ❌ No | ❌ No | Prefer `Contexts` instead |
544
+ | **User** | ✅ Partially | ✅ Yes | User attribution and filtering |
545
+
546
+ ---
547
+
548
+ ## `BeforeSend` and Filtering Hooks
549
+
550
+ ### `BeforeSend` — Modify or Drop Error Events
551
+
552
+ Called immediately before transmission — last in the processing pipeline.
553
+ Return `null` to drop the event.
554
+
555
+ ```csharp
556
+ SentrySdk.Init(options =>
557
+ {
558
+ // Simple variant
559
+ options.SetBeforeSend(@event =>
560
+ {
561
+ // Drop noisy exceptions
562
+ if (@event.Exception?.Message.Contains("Noisy Exception") == true)
563
+ return null;
564
+
565
+ // Scrub server name for privacy
566
+ @event.ServerName = null;
567
+
568
+ return @event;
569
+ });
570
+
571
+ // Full variant with SentryHint
572
+ options.SetBeforeSend((@event, hint) =>
573
+ {
574
+ if (@event.Exception is SqlException sqlEx && sqlEx.Number == 1205)
575
+ {
576
+ // Deadlock — enrich rather than drop
577
+ @event.SetTag("sql.error_number", sqlEx.Number.ToString());
578
+ }
579
+
580
+ return @event;
581
+ });
582
+ });
583
+ ```
584
+
585
+ ### `BeforeSendTransaction` — Modify or Drop Performance Events
586
+
587
+ ```csharp
588
+ options.SetBeforeSendTransaction((transaction, hint) =>
589
+ {
590
+ if (transaction.Name == "GET /health")
591
+ return null; // Drop health-check transactions
592
+ return transaction;
593
+ });
594
+ ```
595
+
596
+ ### `BeforeBreadcrumb` — Filter or Modify Breadcrumbs
597
+
598
+ ```csharp
599
+ options.SetBeforeBreadcrumb(breadcrumb =>
600
+ breadcrumb.Category == "Spammy.Logger"
601
+ ? null // null DROPS the breadcrumb
602
+ : breadcrumb); // returning it KEEPS it (optionally modified)
603
+
604
+ // Full variant with hint
605
+ options.SetBeforeBreadcrumb((breadcrumb, hint) =>
606
+ {
607
+ if (breadcrumb.Level == BreadcrumbLevel.Debug)
608
+ return null;
609
+ return breadcrumb;
610
+ });
611
+ ```
612
+
613
+ ### `BeforeSendLog`
614
+
615
+ ```csharp
616
+ options.SetBeforeSendLog(log =>
617
+ {
618
+ if (log.Level < SentryLogLevel.Warning)
619
+ return null;
620
+ return log;
621
+ });
622
+ ```
623
+
624
+ ---
625
+
626
+ ## Fingerprinting and Custom Grouping
627
+
628
+ All events have a fingerprint.
629
+ Events with the same fingerprint group into the same issue.
630
+ The default fingerprint is computed from the stack trace.
631
+ Override it in `BeforeSend` or directly on a scope/event.
632
+
633
+ ### Group more aggressively (collapse all matching into one issue)
634
+
635
+ ```csharp
636
+ options.SetBeforeSend(@event =>
637
+ {
638
+ if (@event.Exception is SqlConnectionException)
639
+ {
640
+ // All SqlConnectionExceptions → one issue
641
+ @event.SetFingerprint(new[] { "database-connection-error" });
642
+ }
643
+ return @event;
644
+ });
645
+ ```
646
+
647
+ ### Group with greater granularity (split issues using `{{ default }}`)
648
+
649
+ ```csharp
650
+ options.SetBeforeSend(@event =>
651
+ {
652
+ if (@event.Exception is MyRpcException ex)
653
+ {
654
+ @event.SetFingerprint(new[]
655
+ {
656
+ "{{ default }}", // keep Sentry's default hash
657
+ ex.Function, // split by RPC function
658
+ ex.Code.ToString() // split by status code
659
+ });
660
+ }
661
+ return @event;
662
+ });
663
+ ```
664
+
665
+ ### Set fingerprint directly on scope or event
666
+
667
+ ```csharp
668
+ // On scope — applies to all subsequent events in this scope
669
+ SentrySdk.ConfigureScope(scope =>
670
+ {
671
+ scope.Fingerprint = new[] { "my-custom-fingerprint" };
672
+ });
673
+
674
+ // On a specific event
675
+ var evt = new SentryEvent(exception);
676
+ evt.Fingerprint = new[] { "{{ default }}", "additional-key" };
677
+ SentrySdk.CaptureEvent(evt);
678
+ ```
679
+
680
+ ### Fingerprint template variables
681
+
682
+ | Variable | Description |
683
+ | ------------------- | ------------------------------------------------------------ |
684
+ | `{{ default }}` | Sentry’s normally computed hash (extend rather than replace) |
685
+ | `{{ transaction }}` | Current transaction name |
686
+ | `{{ function }}` | Top function in stack trace |
687
+ | `{{ type }}` | Exception type name |
688
+
689
+ ---
690
+
691
+ ## Exception Filters
692
+
693
+ ### Filter by exception type
694
+
695
+ ```csharp
696
+ SentrySdk.Init(options =>
697
+ {
698
+ // Also suppresses TaskCanceledException (derives from OperationCanceledException)
699
+ options.AddExceptionFilterForType<OperationCanceledException>();
700
+ options.AddExceptionFilterForType<MyBusinessException>();
701
+ });
702
+ ```
703
+
704
+ ### Custom `IExceptionFilter`
705
+
706
+ ```csharp
707
+ public class MyExceptionFilter : IExceptionFilter
708
+ {
709
+ public bool Filter(Exception ex)
710
+ {
711
+ // Return true to DROP the exception (not sent to Sentry)
712
+ return ex is MyCustomException mce && mce.IsExpected;
713
+ }
714
+ }
715
+
716
+ SentrySdk.Init(options =>
717
+ {
718
+ options.AddExceptionFilter(new MyExceptionFilter());
719
+ });
720
+ ```
721
+
722
+ ### Deduplication
723
+
724
+ ```csharp
725
+ SentrySdk.Init(options =>
726
+ {
727
+ // Default: All ^ InnerException
728
+ options.DeduplicateMode =
729
+ DeduplicateMode.SameEvent |
730
+ DeduplicateMode.SameExceptionInstance;
731
+
732
+ // Disable entirely
733
+ options.DisableDuplicateEventDetection();
734
+ });
735
+ ```
736
+
737
+ **DeduplicateMode flags:** `SameEvent`, `SameExceptionInstance`, `InnerException`,
738
+ `AggregateException`, `All`
739
+
740
+ ---
741
+
742
+ ## Unhandled Exception Capture
743
+
744
+ ### WPF
745
+
746
+ ```csharp
747
+ // App.xaml.cs — must be in constructor, NOT OnStartup()
748
+ public partial class App : Application
749
+ {
750
+ public App()
751
+ {
752
+ SentrySdk.Init(options =>
753
+ {
754
+ options.Dsn = "https://...@sentry.io/...";
755
+ options.IsGlobalModeEnabled = true; // Required for desktop apps
756
+ options.TracesSampleRate = 1.0;
757
+ });
758
+
759
+ // Hook WPF dispatcher-level unhandled exceptions
760
+ DispatcherUnhandledException += App_DispatcherUnhandledException;
761
+ }
762
+
763
+ void App_DispatcherUnhandledException(
764
+ object sender, DispatcherUnhandledExceptionEventArgs e)
765
+ {
766
+ SentrySdk.CaptureException(e.Exception);
767
+ e.Handled = true; // Prevent the WPF default crash dialog
768
+ }
769
+ }
770
+ ```
771
+
772
+ > **`IsGlobalModeEnabled = true`** is required for WPF — ensures background thread
773
+ > exceptions share the same scope as the UI thread.
774
+
775
+ > **Critical:** Initialize in the `App()` constructor, not `OnStartup()`. The
776
+ > constructor runs before any dispatcher frames, ensuring the unhandled exception hook
777
+ > is registered first.
778
+
779
+ ### MAUI
780
+
781
+ ```csharp
782
+ // MauiProgram.cs
783
+ public static MauiApp CreateMauiApp()
784
+ {
785
+ var builder = MauiApp.CreateBuilder();
786
+ builder
787
+ .UseMauiApp<App>()
788
+ .UseSentry(options =>
789
+ {
790
+ options.Dsn = "https://...@sentry.io/...";
791
+ options.TracesSampleRate = 1.0;
792
+
793
+ // Optional — all false by default (PII risk)
794
+ options.IncludeTextInBreadcrumbs = false;
795
+ options.IncludeTitleInBreadcrumbs = false;
796
+ options.IncludeBackgroundingStateInBreadcrumbs = false;
797
+ });
798
+ return builder.Build();
799
+ }
800
+ ```
801
+
802
+ **MAUI platform coverage:**
803
+
804
+ | Platform | Integration |
805
+ | ------------------ | ------------------------------------------------------------------------------- |
806
+ | Android | `AppDomainUnhandledExceptionIntegration` + native Android SDK |
807
+ | iOS / Mac Catalyst | `RuntimeMarshalManagedExceptionIntegration` + native Cocoa SDK |
808
+ | Windows (WinUI) | `AppDomainUnhandledExceptionIntegration` + `WinUIUnhandledExceptionIntegration` |
809
+
810
+ ### Windows Forms
811
+
812
+ ```csharp
813
+ // Program.cs
814
+ [STAThread]
815
+ static void Main()
816
+ {
817
+ Application.EnableVisualStyles();
818
+ Application.SetCompatibleTextRenderingDefault(false);
819
+
820
+ // REQUIRED: makes WinForms re-throw instead of swallowing exceptions
821
+ Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
822
+
823
+ using (SentrySdk.Init(options =>
824
+ {
825
+ options.Dsn = "https://...@sentry.io/...";
826
+ options.IsGlobalModeEnabled = true;
827
+ options.TracesSampleRate = 1.0;
828
+ }))
829
+ {
830
+ Application.Run(new MainForm());
831
+ }
832
+ }
833
+ ```
834
+
835
+ ### Console App
836
+
837
+ ```csharp
838
+ // Program.cs
839
+ SentrySdk.Init(options =>
840
+ {
841
+ options.Dsn = "https://...@sentry.io/...";
842
+ options.TracesSampleRate = 1.0;
843
+ });
844
+
845
+ // SDK 3.31.0+ handles flush on exit automatically
846
+ // For older SDKs, wrap in: using var _ = SentrySdk.Init(...);
847
+ ```
848
+
849
+ ### Disabling Built-in Integrations
850
+
851
+ ```csharp
852
+ SentrySdk.Init(options =>
853
+ {
854
+ options.DisableAppDomainUnhandledExceptionCapture();
855
+ options.DisableUnobservedTaskExceptionCapture();
856
+ options.DisableAppDomainProcessExitFlush();
857
+ options.DisableRuntimeMarshalManagedExceptionCapture(); // iOS/MacCatalyst
858
+ });
859
+ ```
860
+
861
+ ---
862
+
863
+ ## Event Processors
864
+
865
+ Unlike `BeforeSend` (only one allowed), multiple event processors can be registered at
866
+ different scopes:
867
+
868
+ ```csharp
869
+ // Global — runs for all events
870
+ public class MyEventProcessor : ISentryEventProcessor
871
+ {
872
+ public SentryEvent? Process(SentryEvent @event)
873
+ {
874
+ if (@event.Exception is BackgroundJobException)
875
+ return null; // Drop — null discards the event
876
+
877
+ @event.SetTag("app.layer", "background-worker");
878
+ @event.ServerName = null; // Scrub hostname
879
+
880
+ return @event;
881
+ }
882
+ }
883
+
884
+ // Register globally via options
885
+ SentrySdk.Init(options =>
886
+ {
887
+ options.AddEventProcessor(new MyEventProcessor());
888
+ });
889
+
890
+ // Register on current + following scopes
891
+ SentrySdk.ConfigureScope(scope =>
892
+ {
893
+ scope.AddEventProcessor(new MyEventProcessor());
894
+ });
895
+
896
+ // Register for a single event only
897
+ SentrySdk.CaptureException(ex, scope =>
898
+ {
899
+ scope.AddEventProcessor(new MyEventProcessor());
900
+ });
901
+ ```
902
+
903
+ ### Exception processor (runs before the main chain)
904
+
905
+ ```csharp
906
+ public class MyExceptionProcessor : ISentryEventExceptionProcessor
907
+ {
908
+ public void Process(Exception exception, SentryEvent sentryEvent)
909
+ {
910
+ if (exception is HttpRequestException httpEx)
911
+ {
912
+ sentryEvent.SetTag("http.status", httpEx.StatusCode?.ToString() ?? "unknown");
913
+ }
914
+ }
915
+ }
916
+
917
+ SentrySdk.Init(options =>
918
+ {
919
+ options.AddExceptionProcessor(new MyExceptionProcessor());
920
+ });
921
+ ```
922
+
923
+ **Processor execution order:**
924
+
925
+ 1. `ISentryEventExceptionProcessor` — exception-specific processors
926
+ 2. `ISentryEventProcessor` — general event processors
927
+ 3. `SetBeforeSend` / `SetBeforeSendTransaction` — **always last**
928
+
929
+ ---
930
+
931
+ ## User Feedback
932
+
933
+ ### Programmatic API
934
+
935
+ ```csharp
936
+ // Capture an event first to get an ID
937
+ var eventId = SentrySdk.CaptureMessage("An event that will receive user feedback.");
938
+
939
+ // Submit user feedback linked to that event
940
+ SentrySdk.CaptureFeedback(
941
+ message: "It broke when I clicked submit.",
942
+ contactEmail: "user@example.com",
943
+ name: "Jane Doe",
944
+ associatedEventId: eventId);
945
+ ```
946
+
947
+ **Full signature:**
948
+
949
+ ```csharp
950
+ SentryId SentrySdk.CaptureFeedback(
951
+ string message,
952
+ string? contactEmail = null,
953
+ string? name = null,
954
+ string? replayId = null,
955
+ string? url = null,
956
+ SentryId? associatedEventId = null,
957
+ Scope? scope = null,
958
+ SentryHint? hint = null)
959
+ ```
960
+
961
+ **Using `SentryFeedback` object:**
962
+
963
+ ```csharp
964
+ var feedback = new SentryFeedback(
965
+ message: "The checkout button is broken.",
966
+ contactEmail: "user@example.com",
967
+ name: "John Smith",
968
+ associatedEventId: SentrySdk.LastEventId);
969
+
970
+ SentrySdk.CaptureFeedback(feedback);
971
+ ```
972
+
973
+ > **Validation:** Sentry rejects feedback with invalid email addresses.
974
+ > Pre-validate email format before calling the API.
975
+
976
+ ### Crash-Report Modal (JavaScript widget on error pages)
977
+
978
+ For ASP.NET Core web apps, show the browser-based report dialog on error response pages:
979
+
980
+ ```html
981
+ <!-- Include Sentry JS SDK -->
982
+ <script src="https://browser.sentry-cdn.com/10.40.0/bundle.min.js" crossorigin="anonymous"></script>
983
+
984
+ <!-- Show dialog with the server-side event ID -->
985
+ <script>
986
+ Sentry.init({ dsn: "https://...@sentry.io/..." });
987
+ Sentry.showReportDialog({ eventId: "@ViewBag.SentryEventId" });
988
+ </script>
989
+ ```
990
+
991
+ ```csharp
992
+ // In your error controller or exception handler middleware
993
+ ViewBag.SentryEventId = SentrySdk.LastEventId;
994
+ ```
995
+
996
+ ---
997
+
998
+ ## Error Capture Quick Reference
999
+
1000
+ ### Scenario Coverage Table
1001
+
1002
+ | Scenario | Auto Captured? | Solution |
1003
+ | ------------------------------------ | -------------- | ---------------------------------------------------- |
1004
+ | Unhandled exception (all frameworks) | ✅ Yes | `AppDomain.UnhandledException` integration |
1005
+ | Unobserved Task exception | ✅ Yes | `TaskScheduler.UnobservedTaskException` integration |
1006
+ | ASP.NET Core request error | ✅ Yes | Sentry middleware |
1007
+ | WPF `DispatcherUnhandledException` | ✅ Yes | Hook in `App()` constructor |
1008
+ | MAUI unhandled exception | ✅ Yes | Platform-specific native integrations |
1009
+ | WinForms unhandled exception | ✅ Yes | Requires `SetUnhandledExceptionMode(ThrowException)` |
1010
+ | `try/catch` with graceful return | ❌ No | `SentrySdk.CaptureException(ex)` before return |
1011
+ | `try/catch` with re-throw | ✅ Yes | Bubbles to unhandled exception handler |
1012
+ | Background thread exception | ✅ Yes | `IsGlobalModeEnabled = true` for desktop apps |
1013
+
1014
+ ### API Quick Reference
1015
+
1016
+ ```csharp
1017
+ // ── Capture ───────────────────────────────────────────────────────────────
1018
+ SentrySdk.CaptureException(ex)
1019
+ SentrySdk.CaptureException(ex, scope => { scope.SetTag("key", "val"); })
1020
+ SentrySdk.CaptureMessage("text")
1021
+ SentrySdk.CaptureMessage("text", SentryLevel.Warning)
1022
+
1023
+ // ── User ──────────────────────────────────────────────────────────────────
1024
+ SentrySdk.ConfigureScope(scope => scope.User = new SentryUser { Id = "42", Email = "..." });
1025
+ SentrySdk.ConfigureScope(scope => scope.User = new SentryUser()); // clear on logout
1026
+
1027
+ // ── Tags (searchable) ─────────────────────────────────────────────────────
1028
+ SentrySdk.ConfigureScope(scope => scope.SetTag("key", "value"));
1029
+ SentrySdk.ConfigureScope(scope => scope.UnsetTag("key"));
1030
+
1031
+ // ── Contexts (structured, non-searchable) ─────────────────────────────────
1032
+ SentrySdk.ConfigureScope(scope => scope.Contexts["name"] = new { Key = "value" });
1033
+
1034
+ // ── Breadcrumbs ───────────────────────────────────────────────────────────
1035
+ SentrySdk.AddBreadcrumb(message: "...", category: "auth", level: BreadcrumbLevel.Info);
1036
+
1037
+ // ── Scope isolation ───────────────────────────────────────────────────────
1038
+ using (SentrySdk.PushScope())
1039
+ {
1040
+ SentrySdk.ConfigureScope(scope => scope.SetTag("key", "value"));
1041
+ SentrySdk.CaptureException(ex);
1042
+ } // tag is cleared after this block
1043
+
1044
+ // ── Fingerprinting ────────────────────────────────────────────────────────
1045
+ SentrySdk.ConfigureScope(scope => scope.Fingerprint = new[] { "group-key" });
1046
+ // In BeforeSend: @event.SetFingerprint(new[] { "{{ default }}", "extra-dim" });
1047
+
1048
+ // ── Hooks (in SentrySdk.Init) ─────────────────────────────────────────────
1049
+ options.SetBeforeSend((@event, hint) => @event) // return null to drop
1050
+ options.SetBeforeSendTransaction((txn, hint) => txn)
1051
+ options.SetBeforeBreadcrumb((crumb, hint) => crumb) // return null to drop
1052
+ options.AddExceptionFilterForType<OperationCanceledException>()
1053
+
1054
+ // ── Flush ─────────────────────────────────────────────────────────────────
1055
+ SentrySdk.Flush(TimeSpan.FromSeconds(5));
1056
+ await SentrySdk.FlushAsync(TimeSpan.FromSeconds(5));
1057
+ ```
1058
+
1059
+ ---
1060
+
1061
+ ## Configuration Options Reference
1062
+
1063
+ | Option | Type | Default | Description |
1064
+ | ----------------------- | ---------------------------- | ---------------------- | ----------------------------------------------------------------- |
1065
+ | `Dsn` | `string` | — | DSN from Sentry project settings; also reads `SENTRY_DSN` env var |
1066
+ | `Release` | `string?` | — | App release version; also reads `SENTRY_RELEASE` |
1067
+ | `Environment` | `string?` | — | Deployment environment; also reads `SENTRY_ENVIRONMENT` |
1068
+ | `SampleRate` | `float?` | `null` (sends 100%) | Error event sampling rate (0–1) |
1069
+ | `TracesSampleRate` | `double?` | `null` (tracing off) | Transaction sampling rate (0–1) |
1070
+ | `AttachStacktrace` | `bool` | `true` | Attach stack traces to message events too |
1071
+ | `SendDefaultPii` | `bool` | `false` | Include IP, username, headers |
1072
+ | `MaxBreadcrumbs` | `int` | `100` | Max breadcrumbs per event |
1073
+ | `IsGlobalModeEnabled` | `bool` | `false` | Singleton scope for desktop apps |
1074
+ | `Debug` | `bool` | `false` | Log SDK diagnostics to console |
1075
+ | `DiagnosticLevel` | `SentryLevel` | `Debug` | Min level for SDK diagnostic logs |
1076
+ | `DeduplicateMode` | `DeduplicateMode` | `All ^ InnerException` | Duplicate event detection strategy |
1077
+ | `MaxAttachmentSize` | `long` | `20 MiB` | Max attachment size in bytes |
1078
+ | `DefaultTags` | `Dictionary<string, string>` | `{}` | Tags added to every event |
1079
+ | `CacheDirectoryPath` | `string?` | `null` | Path for offline envelope caching |
1080
+ | `ShutdownTimeout` | `TimeSpan` | `2s` | Flush timeout on SDK shutdown |
1081
+ | `CaptureFailedRequests` | `bool` | `true` | Capture HTTP client error responses |
1082
+ | `EnableLogs` | `bool` | `false` | Enable Sentry structured logging |
1083
+ | `StackTraceMode` | `StackTraceMode` | `Enhanced` | `Enhanced` or `Original` |
1084
+
1085
+ ---
1086
+
1087
+ ## Troubleshooting
1088
+
1089
+ | Issue | Solution |
1090
+ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
1091
+ | Caught exceptions not appearing in Sentry | Any `try/catch` that doesn’t re-throw must call `SentrySdk.CaptureException(ex)` before returning |
1092
+ | WPF exceptions from background threads missing | Set `options.IsGlobalModeEnabled = true`; initialize in `App()` constructor, not `OnStartup()` |
1093
+ | WinForms exceptions not captured | Call `Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)` before `SentrySdk.Init` |
1094
+ | Events dropped after process exit (console/CLI) | SDK 3.31.0+ handles this automatically; on older versions wrap `Init` result in `using var _ = SentrySdk.Init(...)` |
1095
+ | Stack traces show minified/optimized frames | Enable symbol upload via MSBuild properties (`SentryOrg`, `SentryProject`, `SentryAuthToken`) |
1096
+ | Duplicate events in Sentry | Check `DeduplicateMode`; `AggregateException` wrapping can cause same exception to appear multiple times |
1097
+ | Missing user data on events | For ASP.NET Core, enable `SendDefaultPii = true` or register a custom `ISentryUserFactory`; for desktop apps ensure `IsGlobalModeEnabled = true` |
1098
+ | `OperationCanceledException` flooding Sentry | Filter with `options.AddExceptionFilterForType<OperationCanceledException>()` |
1099
+ | Events not sent before Lambda/Azure Functions cold start ends | Call `await SentrySdk.FlushAsync(TimeSpan.FromSeconds(5))` at the end of your handler |
1100
+ | SDK reports `IsEnabled = false` | DSN not set or set to empty string; check `SENTRY_DSN` env var or options initialization order |