celery.tsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import Alert from 'sentry/components/alert';
  4. import {CodeSnippet} from 'sentry/components/codeSnippet';
  5. import ExternalLink from 'sentry/components/links/externalLink';
  6. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  7. import {
  8. type Docs,
  9. DocsPageLocation,
  10. type DocsParams,
  11. type OnboardingConfig,
  12. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  13. import {getPythonMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
  14. import {
  15. AlternativeConfiguration,
  16. crashReportOnboardingPython,
  17. } from 'sentry/gettingStartedDocs/python/python';
  18. import {t, tct} from 'sentry/locale';
  19. import {space} from 'sentry/styles/space';
  20. type Params = DocsParams;
  21. const getInstallSnippet = () => `pip install --upgrade 'sentry-sdk[celery]'`;
  22. const getSdkSetupSnippet = (params: Params) => `
  23. import sentry_sdk
  24. sentry_sdk.init(
  25. dsn="${params.dsn.public}",${
  26. params.isPerformanceSelected
  27. ? `
  28. # Set traces_sample_rate to 1.0 to capture 100%
  29. # of transactions for tracing.
  30. traces_sample_rate=1.0,`
  31. : ''
  32. }${
  33. params.isProfilingSelected &&
  34. params.profilingOptions?.defaultProfilingMode !== 'continuous'
  35. ? `
  36. # Set profiles_sample_rate to 1.0 to profile 100%
  37. # of sampled transactions.
  38. # We recommend adjusting this value in production.
  39. profiles_sample_rate=1.0,`
  40. : ''
  41. }
  42. )${
  43. params.isProfilingSelected &&
  44. params.profilingOptions?.defaultProfilingMode === 'continuous'
  45. ? `
  46. # Manually call start_profiler and stop_profiler
  47. # to profile the code in between
  48. sentry_sdk.profiler.start_profiler()
  49. # this code will be profiled
  50. #
  51. # Calls to stop_profiler are optional - if you don't stop the profiler, it will keep profiling
  52. # your application until the process exits or stop_profiler is called.
  53. sentry_sdk.profiler.stop_profiler()`
  54. : ''
  55. }`;
  56. const onboarding: OnboardingConfig = {
  57. introduction: () =>
  58. tct('The celery integration adds support for the [link:Celery Task Queue System].', {
  59. link: <ExternalLink href="https://docs.celeryq.dev/en/stable/" />,
  60. }),
  61. install: (params: Params) => [
  62. {
  63. type: StepType.INSTALL,
  64. description: tct(
  65. 'Install [code:sentry-sdk] from PyPI with the [code:celery] extra:',
  66. {
  67. code: <code />,
  68. }
  69. ),
  70. configurations: [
  71. {
  72. description:
  73. params.docsLocation === DocsPageLocation.PROFILING_PAGE
  74. ? tct(
  75. 'You need a minimum version [code:1.18.0] of the [code:sentry-python] SDK for the profiling feature.',
  76. {
  77. code: <code />,
  78. }
  79. )
  80. : undefined,
  81. language: 'bash',
  82. code: getInstallSnippet(),
  83. },
  84. ],
  85. },
  86. ],
  87. configure: (params: Params) => [
  88. {
  89. type: StepType.CONFIGURE,
  90. description: (
  91. <div>
  92. <p>
  93. {tct(
  94. 'If you have the [code:celery] package in your dependencies, the Celery integration will be enabled automatically when you initialize the Sentry SDK.',
  95. {
  96. code: <code />,
  97. }
  98. )}
  99. </p>
  100. <p>
  101. {tct(
  102. 'Make sure that the call to [code:init] is loaded on worker startup, and not only in the module where your tasks are defined. Otherwise, the initialization happens too late and events might end up not being reported.',
  103. {
  104. code: <code />,
  105. }
  106. )}
  107. </p>
  108. </div>
  109. ),
  110. configurations: [
  111. {
  112. language: 'python',
  113. code: getSdkSetupSnippet(params),
  114. },
  115. ],
  116. additionalInfo: (
  117. <Fragment>
  118. {params.isProfilingSelected &&
  119. params.profilingOptions?.defaultProfilingMode === 'continuous' && (
  120. <Fragment>
  121. <AlternativeConfiguration />
  122. <br />
  123. </Fragment>
  124. )}
  125. <h5>{t('Standalone Setup')}</h5>
  126. {t("If you're using Celery standalone, there are two ways to set this up:")}
  127. <ul>
  128. <li>
  129. {tct(
  130. "Initializing the SDK in the configuration file loaded with Celery's [code:--config] parameter",
  131. {
  132. code: <code />,
  133. }
  134. )}
  135. </li>
  136. <li>
  137. {tct(
  138. 'Initializing the SDK by hooking it to either the [celerydInit: celeryd_init] or [workerInit: worker_init] signals:',
  139. {
  140. celerydInit: (
  141. <ExternalLink href="https://docs.celeryq.dev/en/stable/userguide/signals.html?#celeryd-init" />
  142. ),
  143. workerInit: (
  144. <ExternalLink href="https://docs.celeryq.dev/en/stable/userguide/signals.html?#worker-init" />
  145. ),
  146. }
  147. )}
  148. <CodeSnippet dark language="python">
  149. {`import sentry_sdk
  150. from celery import Celery, signals
  151. app = Celery("myapp")
  152. #@signals.worker_init.connect
  153. @signals.celeryd_init.connect
  154. def init_sentry(**_kwargs):
  155. sentry_sdk.init(...) # same as above
  156. `}
  157. </CodeSnippet>
  158. </li>
  159. </ul>
  160. <h5>{t('Setup With Django')}</h5>
  161. <p>
  162. {tct(
  163. "If you're using Celery with Django in a conventional setup, have already initialized the SDK in [settingsLink:your settings.py], and have Celery using the same settings with [celeryDocsLinks:config_from_object], you don't need to initialize the SDK separately for Celery.",
  164. {
  165. settingsLink: (
  166. <ExternalLink href="https://docs.sentry.io/platforms/python/guides/django/#configure" />
  167. ),
  168. celeryDocsLinks: (
  169. <ExternalLink href="https://docs.celeryq.dev/en/stable/django/first-steps-with-django.html" />
  170. ),
  171. }
  172. )}
  173. </p>
  174. </Fragment>
  175. ),
  176. },
  177. ],
  178. verify: () => [
  179. {
  180. type: StepType.VERIFY,
  181. description: (
  182. <Fragment>
  183. <p>
  184. {t(
  185. "To verify if your SDK is initialized on worker start, you can pass `debug=True` to `sentry_sdk.init()` to see extra output when the SDK is initialized. If the output appears during worker startup and not only after a task has started, then it's working properly."
  186. )}
  187. </p>
  188. <AlertWithMarginBottom type="info">
  189. {tct(
  190. `Sentry uses custom message headers for distributed tracing. For Celery versions 4.x, with [celeryDocLink: message protocol of version 1], this functionality is broken, and Celery fails to propagate custom headers to the worker. Protocol version 2, which is the default since Celery version 4.0, is not affected.
  191. The fix for the custom headers propagation issue was introduced to Celery project ([celeryPRLink: PR]) starting with version 5.0.1. However, the fix was not backported to versions 4.x.
  192. `,
  193. {
  194. celeryDocLink: (
  195. <ExternalLink href="https://docs.celeryq.dev/en/stable/internals/protocol.html#version-1" />
  196. ),
  197. celeryPRLink: (
  198. <ExternalLink href="https://github.com/celery/celery/pull/6374" />
  199. ),
  200. }
  201. )}
  202. </AlertWithMarginBottom>
  203. </Fragment>
  204. ),
  205. },
  206. ],
  207. };
  208. const docs: Docs = {
  209. onboarding,
  210. customMetricsOnboarding: getPythonMetricsOnboarding({
  211. installSnippet: getInstallSnippet(),
  212. }),
  213. crashReportOnboarding: crashReportOnboardingPython,
  214. };
  215. export default docs;
  216. const AlertWithMarginBottom = styled(Alert)`
  217. margin-top: ${space(2)};
  218. margin-bottom: 0;
  219. `;