import {Fragment} from 'react'; import styled from '@emotion/styled'; import {Alert} from 'sentry/components/alert'; 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 getConfigureSnippet = (params: Params) => ` import ( "fmt" "net/http" "github.com/getsentry/sentry-go" sentryfiber "github.com/getsentry/sentry-go/fiber" ) // To initialize Sentry's handler, you need to initialize Sentry itself beforehand if err := sentry.Init(sentry.ClientOptions{ Dsn: "${params.dsn}", // Set TracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. // We recommend adjusting this value in production, TracesSampleRate: 1.0, }); err != nil { fmt.Printf("Sentry initialization failed: %v\\n", err) } // Later in the code sentryHandler := sentryfiber.New(sentryfiber.Options{ Repanic: true, WaitForDelivery: true, }) enhanceSentryEvent := func(ctx *fiber.Ctx) error { if hub := sentryfiber.GetHubFromContext(ctx); hub != nil { hub.Scope().SetTag("someRandomTag", "maybeYouNeedIt") } return ctx.Next() } app := fiber.New() app.Use(sentryHandler) app.All("/foo", enhanceSentryEvent, func(c *fiber.Ctx) error { panic("y tho") }) app.All("/", func(ctx *fiber.Ctx) error { if hub := sentryfiber.GetHubFromContext(ctx); hub != nil { hub.WithScope(func(scope *sentry.Scope) { scope.SetExtra("unwantedQuery", "someQueryDataMaybe") hub.CaptureMessage("User provided unwanted query string, but we recovered just fine") }) } return ctx.SendStatus(fiber.StatusOK) }) if err := app.Listen(":3000"); err != nil { panic(err) }`; const getOptionsSnippet = () => ` // Repanic configures whether Sentry should repanic after recovery, in most cases it should be set to true, // as fiber includes its own Recover middleware that handles http responses. Repanic bool // WaitForDelivery configures whether you want to block the request before moving forward with the response. // Because Fiber's "Recover" handler doesn't restart the application, // it's safe to either skip this option or set it to "false". WaitForDelivery bool // Timeout for the event delivery requests. Timeout time.Duration`; const getUsageSnippet = () => ` sentryHandler := sentryfiber.New(sentryfiber.Options{ Repanic: true, WaitForDelivery: true, }) enhanceSentryEvent := func(ctx *fiber.Ctx) error { if hub := sentryfiber.GetHubFromContext(ctx); hub != nil { hub.Scope().SetTag("someRandomTag", "maybeYouNeedIt") } return ctx.Next() } app := fiber.New() app.Use(sentryHandler) app.All("/foo", enhanceSentryEvent, func(c *fiber.Ctx) error { panic("y tho") }) app.All("/", func(ctx *fiber.Ctx) error { if hub := sentryfiber.GetHubFromContext(ctx); hub != nil { hub.WithScope(func(scope *sentry.Scope) { scope.SetExtra("unwantedQuery", "someQueryDataMaybe") hub.CaptureMessage("User provided unwanted query string, but we recovered just fine") }) } return ctx.SendStatus(fiber.StatusOK) }) if err := app.Listen(":3000"); err != nil { panic(err) };`; const getBeforeSendSnippet = params => ` sentry.Init(sentry.ClientOptions{ Dsn: "${params.dsn}", BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event { if hint.Context != nil { if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok { // You have access to the original Request here } } return event }, })`; const onboarding: OnboardingConfig = { install: () => [ { type: StepType.INSTALL, description: tct('Install our Go Fiber SDK using [code:go get]:', { code: <code />, }), configurations: [ { language: 'bash', code: 'go get github.com/getsentry/sentry-go/fiber', }, ], }, ], configure: params => [ { type: StepType.CONFIGURE, description: t( "Import and initialize the Sentry SDK early in your application's setup:" ), configurations: [ { language: 'go', code: getConfigureSnippet(params), }, { description: ( <Fragment> <strong>{t('Options')}</strong> <p> {tct( '[sentryFiberCode:sentryfiber] accepts a struct of [optionsCode:Options] that allows you to configure how the handler will behave.', {sentryFiberCode: <code />, optionsCode: <code />} )} </p> {t('Currently it respects 3 options:')} </Fragment> ), language: 'go', code: getOptionsSnippet(), }, ], }, { title: t('Usage'), description: ( <Fragment> <p> {tct( "[sentryFiberCode:sentryfiber] attaches an instance of [sentryHubLink:*sentry.Hub] to the [fiberContextCode:*fiber.Ctx], which makes it available throughout the rest of the request's lifetime. You can access it by using the [getHubFromContextCode:sentryfiber.GetHubFromContext()] method on the context itself in any of your proceeding middleware and routes. And it should be used instead of the global [captureMessageCode:sentry.CaptureMessage], [captureExceptionCode:sentry.CaptureException] or any other calls, as it keeps the separation of data between the requests.", { sentryFiberCode: <code />, sentryHubLink: ( <ExternalLink href="https://godoc.org/github.com/getsentry/sentry-go#Hub" /> ), fiberContextCode: <code />, getHubFromContextCode: <code />, captureMessageCode: <code />, captureExceptionCode: <code />, } )} </p> <AlertWithoutMarginBottom> {tct( "Keep in mind that [sentryHubCode:*sentry.Hub] won't be available in middleware attached before [sentryFiberCode:sentryfiber]!", {sentryFiberCode: <code />, sentryHubCode: <code />} )} </AlertWithoutMarginBottom> </Fragment> ), configurations: [ { language: 'go', code: getUsageSnippet(), }, { description: ( <strong> {tct('Accessing Request in [beforeSendCode:BeforeSend] callback', { beforeSendCode: <code />, })} </strong> ), language: 'go', code: getBeforeSendSnippet(params), }, ], }, ], verify: () => [], }; const crashReportOnboarding: OnboardingConfig = { introduction: () => getCrashReportModalIntroduction(), install: (params: Params) => getCrashReportGenericInstallStep(params), configure: () => [ { type: StepType.CONFIGURE, description: getCrashReportModalConfigDescription({ link: 'https://docs.sentry.io/platforms/go/guides/fiber/user-feedback/configuration/#crash-report-modal', }), }, ], verify: () => [], nextSteps: () => [], }; const docs: Docs = { onboarding, replayOnboardingJsLoader, crashReportOnboarding, }; export default docs; const AlertWithoutMarginBottom = styled(Alert)` margin-bottom: 0; `;