python.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. import {SdkProviderEnum as FeatureFlagProviderEnum} from 'sentry/components/events/featureFlags/utils';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  4. import {
  5. type Docs,
  6. DocsPageLocation,
  7. type DocsParams,
  8. type OnboardingConfig,
  9. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  10. import {
  11. getCrashReportBackendInstallStep,
  12. getCrashReportModalConfigDescription,
  13. getCrashReportModalIntroduction,
  14. } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
  15. import {t, tct} from 'sentry/locale';
  16. type Params = DocsParams;
  17. type FeatureFlagConfiguration = {
  18. integrationName: string;
  19. makeCodeSnippet: (dsn: string) => string;
  20. };
  21. const FEATURE_FLAG_CONFIGURATION_MAP: Record<
  22. FeatureFlagProviderEnum,
  23. FeatureFlagConfiguration
  24. > = {
  25. [FeatureFlagProviderEnum.GENERIC]: {
  26. integrationName: ``,
  27. makeCodeSnippet: (_dsn: string) => `import sentry_sdk
  28. from sentry_sdk.feature_flags import add_feature_flag
  29. add_feature_flag('test-flag', False) # Records an evaluation and its result.
  30. sentry_sdk.capture_exception(Exception("Something went wrong!"))`,
  31. },
  32. [FeatureFlagProviderEnum.LAUNCHDARKLY]: {
  33. integrationName: `LaunchDarklyIntegration`,
  34. makeCodeSnippet: (dsn: string) => `import sentry_sdk
  35. from sentry_sdk.integrations.launchdarkly import LaunchDarklyIntegration
  36. import ldclient
  37. sentry_sdk.init(
  38. dsn="${dsn}",
  39. # Add data like request headers and IP for users, if applicable;
  40. # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
  41. send_default_pii=True,
  42. integrations=[
  43. LaunchDarklyIntegration(),
  44. ],
  45. )
  46. client = ldclient.get()
  47. client.variation("hello", Context.create("test-context"), False) # Evaluate a flag with a default value.
  48. sentry_sdk.capture_exception(Exception("Something went wrong!"))`,
  49. },
  50. [FeatureFlagProviderEnum.OPENFEATURE]: {
  51. integrationName: `OpenFeatureIntegration`,
  52. makeCodeSnippet: (dsn: string) => `import sentry_sdk
  53. from sentry_sdk.integrations.openfeature import OpenFeatureIntegration
  54. from openfeature import api
  55. sentry_sdk.init(
  56. dsn="${dsn}",
  57. # Add data like request headers and IP for users, if applicable;
  58. # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
  59. send_default_pii=True,
  60. integrations=[
  61. OpenFeatureIntegration(),
  62. ],
  63. )
  64. client = api.get_client()
  65. client.get_boolean_value("hello", default_value=False) # Evaluate a flag with a default value.
  66. sentry_sdk.capture_exception(Exception("Something went wrong!"))`,
  67. },
  68. [FeatureFlagProviderEnum.STATSIG]: {
  69. integrationName: `StatsigIntegration`,
  70. makeCodeSnippet: (dsn: string) => `import sentry_sdk
  71. from sentry_sdk.integrations.statsig import StatsigIntegration
  72. from statsig.statsig_user import StatsigUser
  73. from statsig import statsig
  74. import time
  75. sentry_sdk.init(
  76. dsn="${dsn}",
  77. # Add data like request headers and IP for users, if applicable;
  78. # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
  79. send_default_pii=True,
  80. integrations=[StatsigIntegration()],
  81. )
  82. statsig.initialize("server-secret-key")
  83. while not statsig.is_initialized():
  84. time.sleep(0.2)
  85. result = statsig.check_gate(StatsigUser("my-user-id"), "my-feature-gate") # Evaluate a flag.
  86. sentry_sdk.capture_exception(Exception("Something went wrong!"))`,
  87. },
  88. [FeatureFlagProviderEnum.UNLEASH]: {
  89. integrationName: `UnleashIntegration`,
  90. makeCodeSnippet: (dsn: string) => `import sentry_sdk
  91. from sentry_sdk.integrations.unleash import UnleashIntegration
  92. from UnleashClient import UnleashClient
  93. sentry_sdk.init(
  94. dsn="${dsn}",
  95. # Add data like request headers and IP for users, if applicable;
  96. # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
  97. send_default_pii=True,
  98. integrations=[UnleashIntegration()],
  99. )
  100. unleash = UnleashClient(...) # See Unleash quickstart.
  101. unleash.initialize_client()
  102. test_flag_enabled = unleash.is_enabled("test-flag") # Evaluate a flag.
  103. sentry_sdk.capture_exception(Exception("Something went wrong!"))`,
  104. },
  105. };
  106. const getInstallSnippet = () => `pip install --upgrade sentry-sdk`;
  107. const getSdkSetupSnippet = (params: Params) => `
  108. import sentry_sdk
  109. sentry_sdk.init(
  110. dsn="${params.dsn.public}",
  111. # Add data like request headers and IP for users,
  112. # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
  113. send_default_pii=True,${
  114. params.isPerformanceSelected
  115. ? `
  116. # Set traces_sample_rate to 1.0 to capture 100%
  117. # of transactions for tracing.
  118. traces_sample_rate=1.0,`
  119. : ''
  120. }${
  121. params.isProfilingSelected &&
  122. params.profilingOptions?.defaultProfilingMode !== 'continuous'
  123. ? `
  124. # Set profiles_sample_rate to 1.0 to profile 100%
  125. # of sampled transactions.
  126. # We recommend adjusting this value in production.
  127. profiles_sample_rate=1.0,`
  128. : ''
  129. }
  130. )${
  131. params.isProfilingSelected &&
  132. params.profilingOptions?.defaultProfilingMode === 'continuous'
  133. ? `
  134. def slow_function():
  135. import time
  136. time.sleep(0.1)
  137. return "done"
  138. def fast_function():
  139. import time
  140. time.sleep(0.05)
  141. return "done"
  142. # Manually call start_profiler and stop_profiler
  143. # to profile the code in between
  144. sentry_sdk.profiler.start_profiler()
  145. for i in range(0, 10):
  146. slow_function()
  147. fast_function()
  148. #
  149. # Calls to stop_profiler are optional - if you don't stop the profiler, it will keep profiling
  150. # your application until the process exits or stop_profiler is called.
  151. sentry_sdk.profiler.stop_profiler()`
  152. : ''
  153. }`;
  154. const onboarding: OnboardingConfig = {
  155. install: (params: Params) => [
  156. {
  157. type: StepType.INSTALL,
  158. description: tct('Install our Python SDK using [code:pip]:', {
  159. code: <code />,
  160. }),
  161. configurations: [
  162. {
  163. description:
  164. params.docsLocation === DocsPageLocation.PROFILING_PAGE
  165. ? tct(
  166. 'You need a minimum version [code:1.18.0] of the [code:sentry-python] SDK for the profiling feature.',
  167. {
  168. code: <code />,
  169. }
  170. )
  171. : undefined,
  172. language: 'bash',
  173. code: getInstallSnippet(),
  174. },
  175. ],
  176. },
  177. ],
  178. configure: (params: Params) => [
  179. {
  180. type: StepType.CONFIGURE,
  181. description: t(
  182. "Import and initialize the Sentry SDK early in your application's setup:"
  183. ),
  184. configurations: [
  185. {
  186. language: 'python',
  187. code: getSdkSetupSnippet(params),
  188. },
  189. ],
  190. additionalInfo: params.isProfilingSelected &&
  191. params.profilingOptions?.defaultProfilingMode === 'continuous' && (
  192. <AlternativeConfiguration />
  193. ),
  194. },
  195. ],
  196. verify: () => [
  197. {
  198. type: StepType.VERIFY,
  199. description: t(
  200. 'One way to verify your setup is by intentionally causing an error that breaks your application.'
  201. ),
  202. configurations: [
  203. {
  204. language: 'python',
  205. description: t(
  206. 'Raise an unhandled Python exception by inserting a divide by zero expression into your application:'
  207. ),
  208. code: 'division_by_zero = 1 / 0',
  209. },
  210. ],
  211. },
  212. ],
  213. };
  214. export const crashReportOnboardingPython: OnboardingConfig = {
  215. introduction: () => getCrashReportModalIntroduction(),
  216. install: (params: Params) => getCrashReportBackendInstallStep(params),
  217. configure: () => [
  218. {
  219. type: StepType.CONFIGURE,
  220. description: getCrashReportModalConfigDescription({
  221. link: 'https://docs.sentry.io/platforms/python/user-feedback/configuration/#crash-report-modal',
  222. }),
  223. },
  224. ],
  225. verify: () => [],
  226. nextSteps: () => [],
  227. };
  228. export const performanceOnboarding: OnboardingConfig = {
  229. introduction: () =>
  230. t(
  231. "Adding Performance to your Python project is simple. Make sure you've got these basics down."
  232. ),
  233. install: onboarding.install,
  234. configure: params => [
  235. {
  236. type: StepType.CONFIGURE,
  237. description: t(
  238. "Configuration should happen as early as possible in your application's lifecycle."
  239. ),
  240. configurations: [
  241. {
  242. description: tct(
  243. "Once this is done, Sentry's Python SDK captures all unhandled exceptions and transactions. Note that [code:enable_tracing] is available in Sentry Python SDK version [code:≥ 1.16.0]. To enable tracing in older SDK versions ([code:≥ 0.11.2]), use [code:traces_sample_rate=1.0].",
  244. {code: <code />}
  245. ),
  246. language: 'python',
  247. code: `
  248. import sentry_sdk
  249. sentry_sdk.init(
  250. dsn="${params.dsn.public}",
  251. traces_sample_rate=1.0,
  252. )`,
  253. additionalInfo: tct(
  254. 'Learn more about tracing [linkTracingOptions:options], how to use the [linkTracesSampler:traces_sampler] function, or how to [linkSampleTransactions:sample transactions].',
  255. {
  256. linkTracingOptions: (
  257. <ExternalLink href="https://docs.sentry.io/platforms/python/configuration/options/#tracing-options" />
  258. ),
  259. linkTracesSampler: (
  260. <ExternalLink href="https://docs.sentry.io/platforms/python/configuration/sampling/" />
  261. ),
  262. linkSampleTransactions: (
  263. <ExternalLink href="https://docs.sentry.io/platforms/python/configuration/sampling/" />
  264. ),
  265. }
  266. ),
  267. },
  268. ],
  269. },
  270. ],
  271. verify: () => [
  272. {
  273. type: StepType.VERIFY,
  274. description: tct(
  275. 'Verify that performance monitoring is working correctly with our [link:automatic instrumentation] by simply using your Python application.',
  276. {
  277. link: (
  278. <ExternalLink href="https://docs.sentry.io/platforms/python/tracing/instrumentation/automatic-instrumentation/" />
  279. ),
  280. }
  281. ),
  282. additionalInfo: tct(
  283. 'You have the option to manually construct a transaction using [link:custom instrumentation].',
  284. {
  285. link: (
  286. <ExternalLink href="https://docs.sentry.io/platforms/python/tracing/instrumentation/custom-instrumentation/" />
  287. ),
  288. }
  289. ),
  290. },
  291. ],
  292. nextSteps: () => [],
  293. };
  294. export function AlternativeConfiguration() {
  295. return (
  296. <div>
  297. {tct(
  298. 'Alternatively, you can also explicitly control continuous profiling or use transaction profiling. See our [link:documentation] for more information.',
  299. {
  300. link: (
  301. <ExternalLink href="https://docs.sentry.io/platforms/python/profiling/" />
  302. ),
  303. }
  304. )}
  305. </div>
  306. );
  307. }
  308. export const featureFlagOnboarding: OnboardingConfig = {
  309. install: () => [],
  310. configure: ({featureFlagOptions = {integration: ''}, dsn}) => {
  311. const {integrationName, makeCodeSnippet} =
  312. FEATURE_FLAG_CONFIGURATION_MAP[
  313. featureFlagOptions.integration as keyof typeof FEATURE_FLAG_CONFIGURATION_MAP
  314. ]!;
  315. return [
  316. {
  317. type: StepType.CONFIGURE,
  318. description:
  319. featureFlagOptions.integration === FeatureFlagProviderEnum.GENERIC
  320. ? `You don't need an integration for a generic usecase. Simply use this API after initializing Sentry.`
  321. : tct('Add [name] to your integrations list.', {
  322. name: <code>{`${integrationName}`}</code>,
  323. }),
  324. configurations: [
  325. {
  326. language: 'python',
  327. code: makeCodeSnippet(dsn.public),
  328. },
  329. ],
  330. },
  331. ];
  332. },
  333. verify: () => [],
  334. nextSteps: () => [],
  335. };
  336. const docs: Docs = {
  337. onboarding,
  338. performanceOnboarding,
  339. crashReportOnboarding: crashReportOnboardingPython,
  340. featureFlagOnboarding,
  341. };
  342. export default docs;