123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- import {Fragment} from 'react';
- import ExternalLink from 'sentry/components/links/externalLink';
- import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
- import type {
- Docs,
- DocsParams,
- OnboardingConfig,
- } from 'sentry/components/onboarding/gettingStartedDoc/types';
- import {
- getCrashReportGenericInstallStep,
- getCrashReportModalConfigDescription,
- getCrashReportModalIntroduction,
- } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
- import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
- import {t, tct} from 'sentry/locale';
- type Params = DocsParams;
- const getInstallSnippet = () => `
- defp deps do
- [
- # ...
- {:sentry, "~> 8.0"},
- {:jason, "~> 1.1"},
- {:hackney, "~> 1.8"},
- # if you are using plug_cowboy
- {:plug_cowboy, "~> 2.3"}
- ]
- end`;
- const getConfigureSnippet = (params: Params) => `
- config :sentry,
- dsn: "${params.dsn}",
- environment_name: :prod,
- enable_source_code_context: true,
- root_source_code_path: File.cwd!(),
- tags: %{
- env: "production"
- },
- included_environments: [:prod]`;
- const getConfigureSnippetMixEnv = (params: Params) => `
- config :sentry, dsn: "${params.dsn}",
- included_environments: [:prod],
- environment_name: Mix.env`;
- const getCustomEnvironmentNameSnippet = (params: Params) => `
- config :sentry, dsn: "${params.dsn}",
- included_environments: ~w(production staging),
- environment_name: System.get_env("RELEASE_LEVEL") || "development"`;
- const getConfigureRouterSnippet = () => `
- # Phoenix
- use Sentry.PlugCapture
- use Phoenix.Endpoint, otp_app: :my_app
- # ...
- plug Plug.Parsers,
- parsers: [:urlencoded, :multipart, :json],
- pass: ["*/*"],
- json_decoder: Phoenix.json_library()
- plug Sentry.PlugContext
- # Plug
- use Plug.Router
- use Sentry.PlugCapture
- # ...
- plug Plug.Parsers,
- parsers: [:urlencoded, :multipart, :json],
- pass: ["*/*"],
- json_decoder: Phoenix.json_library()
- plug Sentry.PlugContext`;
- const getCaptureExceptionSnippet = () => `
- # lib/my_app/application.ex
- def start(_type, _args) do
- Logger.add_backend(Sentry.LoggerBackend)`;
- const getCaptureErrorsSnippet = () => `
- try do
- ThisWillError.really()
- rescue
- my_exception ->
- Sentry.capture_exception(my_exception, [stacktrace: __STACKTRACE__, extra: %{extra: information}])
- end`;
- const onboarding: OnboardingConfig = {
- install: () => [
- {
- type: StepType.INSTALL,
- description: tct(
- 'Edit your [mixCode:mix.exs] file to add it as a dependency and add the [sentryCode::sentry] package to your applications:',
- {sentryCode: <code />, mixCode: <code />}
- ),
- configurations: [
- {
- language: 'elixir',
- description: <p>{tct('Install [code:sentry-sdk]:', {code: <code />})}</p>,
- code: getInstallSnippet(),
- },
- ],
- },
- ],
- configure: params => [
- {
- type: StepType.CONFIGURE,
- description: tct(
- 'Setup the application production environment in your [code:config/prod.exs]',
- {
- code: <code />,
- }
- ),
- configurations: [
- {
- language: 'elixir',
- code: getConfigureSnippet(params),
- },
- {
- description: (
- <Fragment>
- <p>
- {tct(
- 'The [environmentNameCode:environment_name] and [includedEnvironmentsCode:included_environments] work together to determine if and when Sentry should record exceptions. The [environmentNameCode:environment_name] is the name of the current environment. In the example above, we have explicitly set the environment to [prodCode::prod] which works well if you are inside an environment specific configuration like [configCode:config/prod.exs].',
- {
- environmentNameCode: <code />,
- includedEnvironmentsCode: <code />,
- prodCode: <code />,
- configCode: <code />,
- }
- )}
- </p>
- <p>
- {tct(
- 'An alternative is to use [code:Mix.env] in your general configuration file:',
- {code: <code />}
- )}
- </p>
- </Fragment>
- ),
- configurations: [
- {
- language: 'elixir',
- code: getConfigureSnippetMixEnv(params),
- },
- ],
- },
- {
- description: (
- <Fragment>
- <p>
- {tct(
- 'This will set the environment name to whatever the current Mix environment atom is, but it will only send events if the current environment is [prodCode::prod], since that is the only entry in the [includedEnvironmentsCode:included_environments] key.',
- {
- prodCode: <code />,
- includedEnvironmentsCode: <code />,
- }
- )}
- </p>
- {t(
- "You can even rely on more custom determinations of the environment name. It's not uncommon for most applications to have a 'staging' environment. In order to handle this without adding an additional Mix environment, you can set an environment variable that determines the release level."
- )}
- </Fragment>
- ),
- language: 'elixir',
- code: getCustomEnvironmentNameSnippet(params),
- },
- {
- description: (
- <Fragment>
- <p>
- {tct(
- "In this example, we are getting the environment name from the [code:RELEASE_LEVEL] environment variable. If that variable does not exist, it will default to [code:'development']. Now, on our servers, we can set the environment variable appropriately. On our local development machines, exceptions will never be sent, because the default value is not in the list of [code:included_environments].",
- {
- code: <code />,
- }
- )}
- </p>
- <p>
- {tct(
- 'If using an environment with Plug or Phoenix, add the following to [plugRouterCode:Plug.Router] or [phoenixEndpointCode:Phoenix.Endpoint]:',
- {plugRouterCode: <code />, phoenixEndpointCode: <code />}
- )}
- </p>
- </Fragment>
- ),
- language: 'elixir',
- code: getConfigureRouterSnippet(),
- additionalInfo: tct(
- '[sentryPlugContextCode:Sentry.PlugContext] gathers the contextual information for errors, and [sentryPlugCaptureCode:Sentry.PlugCapture] captures and sends any errors that occur in the Plug stack. [sentryPlugContextCode:Sentry.PlugContext] should be below [sentryPlugParsersCode:Plug.Parsers] if you are using it.',
- {
- sentryPlugCaptureCode: <code />,
- sentryPlugContextCode: <code />,
- sentryPlugParsersCode: <code />,
- }
- ),
- },
- ],
- },
- {
- title: t('Capture Crashed Process Exceptions'),
- description: tct(
- 'This library comes with an extension to capture all error messages that the Plug handler might not. This is based on [link:Logger.Backend]. You can add it as a backend when your application starts:',
- {
- link: (
- <ExternalLink href="https://hexdocs.pm/logger/Logger.html#module-backends" />
- ),
- }
- ),
- configurations: [
- {
- language: 'elixir',
- code: getCaptureExceptionSnippet(),
- },
- ],
- },
- {
- title: t('Capturing Errors'),
- description: (
- <Fragment>
- {t(
- 'If you use the LoggerBackend and set up the Plug/Phoenix integrations, all errors will bubble up to Sentry.'
- )}
- <p>{t('Otherwise, we provide a simple way to capture exceptions manually:')}</p>
- </Fragment>
- ),
- configurations: [
- {
- language: 'elixir',
- code: getCaptureErrorsSnippet(),
- },
- ],
- },
- ],
- verify: () => [],
- };
- const crashReportOnboarding: OnboardingConfig = {
- introduction: () => getCrashReportModalIntroduction(),
- install: (params: Params) => getCrashReportGenericInstallStep(params),
- configure: () => [
- {
- type: StepType.CONFIGURE,
- description: getCrashReportModalConfigDescription({
- link: 'https://docs.sentry.io/platforms/elixir/user-feedback/configuration/#crash-report-modal',
- }),
- },
- ],
- verify: () => [],
- nextSteps: () => [],
- };
- const docs: Docs = {
- onboarding,
- replayOnboardingJsLoader,
- crashReportOnboarding,
- };
- export default docs;
|