echo.tsx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Alert} from 'sentry/components/alert';
  4. import ExternalLink from 'sentry/components/links/externalLink';
  5. import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
  6. import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
  7. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  8. import {t, tct} from 'sentry/locale';
  9. // Configuration Start
  10. export const steps = ({
  11. dsn,
  12. }: {
  13. dsn?: string;
  14. } = {}): LayoutProps['steps'] => [
  15. {
  16. type: StepType.INSTALL,
  17. description: (
  18. <p>
  19. {tct('Install our Go Echo SDK using [code:go get]:', {
  20. code: <code />,
  21. })}
  22. </p>
  23. ),
  24. configurations: [
  25. {
  26. language: 'bash',
  27. code: 'go get github.com/getsentry/sentry-go/echo',
  28. },
  29. ],
  30. },
  31. {
  32. type: StepType.CONFIGURE,
  33. description: t(
  34. "Import and initialize the Sentry SDK early in your application's setup:"
  35. ),
  36. configurations: [
  37. {
  38. language: 'go',
  39. code: `
  40. import (
  41. "fmt"
  42. "net/http"
  43. "github.com/getsentry/sentry-go"
  44. sentryecho "github.com/getsentry/sentry-go/echo"
  45. "github.com/labstack/echo/v4"
  46. "github.com/labstack/echo/v4/middleware"
  47. )
  48. // To initialize Sentry's handler, you need to initialize Sentry itself beforehand
  49. if err := sentry.Init(sentry.ClientOptions{
  50. Dsn: "${dsn}",
  51. // Set TracesSampleRate to 1.0 to capture 100%
  52. // of transactions for performance monitoring.
  53. // We recommend adjusting this value in production,
  54. TracesSampleRate: 1.0,
  55. }); err != nil {
  56. fmt.Printf("Sentry initialization failed: %v\n", err)
  57. }
  58. // Then create your app
  59. app := echo.New()
  60. app.Use(middleware.Logger())
  61. app.Use(middleware.Recover())
  62. // Once it's done, you can attach the handler as one of your middleware
  63. app.Use(sentryecho.New(sentryecho.Options{}))
  64. // Set up routes
  65. app.GET("/", func(ctx echo.Context) error {
  66. return ctx.String(http.StatusOK, "Hello, World!")
  67. })
  68. // And run it
  69. app.Logger.Fatal(app.Start(":3000"))
  70. `,
  71. },
  72. {
  73. description: (
  74. <Fragment>
  75. <strong>{t('Options')}</strong>
  76. <p>
  77. {tct(
  78. '[sentryEchoCode:sentryecho] accepts a struct of [optionsCode:Options] that allows you to configure how the handler will behave.',
  79. {sentryEchoCode: <code />, optionsCode: <code />}
  80. )}
  81. </p>
  82. {t('Currently it respects 3 options:')}
  83. </Fragment>
  84. ),
  85. language: 'go',
  86. code: `
  87. // Repanic configures whether Sentry should repanic after recovery, in most cases it should be set to true,
  88. // as echo includes its own Recover middleware that handles http responses.
  89. Repanic bool
  90. // WaitForDelivery configures whether you want to block the request before moving forward with the response.
  91. // Because Echo's "Recover" handler doesn't restart the application,
  92. // it's safe to either skip this option or set it to "false".
  93. WaitForDelivery bool
  94. // Timeout for the event delivery requests.
  95. Timeout time.Duration
  96. `,
  97. },
  98. ],
  99. },
  100. {
  101. title: t('Usage'),
  102. description: (
  103. <Fragment>
  104. <p>
  105. {tct(
  106. "[sentryEchoCode:sentryecho] attaches an instance of [sentryHubLink:*sentry.Hub] to the [echoContextCode:echo.Context], which makes it available throughout the rest of the request's lifetime. You can access it by using the [getHubFromContextCode:sentryecho.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.",
  107. {
  108. sentryEchoCode: <code />,
  109. sentryHubLink: (
  110. <ExternalLink href="https://godoc.org/github.com/getsentry/sentry-go#Hub" />
  111. ),
  112. echoContextCode: <code />,
  113. getHubFromContextCode: <code />,
  114. captureMessageCode: <code />,
  115. captureExceptionCode: <code />,
  116. }
  117. )}
  118. </p>
  119. <AlertWithoutMarginBottom>
  120. {tct(
  121. "Keep in mind that [sentryHubCode:*sentry.Hub] won't be available in middleware attached before [sentryEchoCode:sentryecho]!",
  122. {sentryEchoCode: <code />, sentryHubCode: <code />}
  123. )}
  124. </AlertWithoutMarginBottom>
  125. </Fragment>
  126. ),
  127. configurations: [
  128. {
  129. language: 'go',
  130. code: `
  131. app := echo.New()
  132. app.Use(middleware.Logger())
  133. app.Use(middleware.Recover())
  134. app.Use(sentryecho.New(sentryecho.Options{
  135. Repanic: true,
  136. }))
  137. app.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
  138. return func(ctx echo.Context) error {
  139. if hub := sentryecho.GetHubFromContext(ctx); hub != nil {
  140. hub.Scope().SetTag("someRandomTag", "maybeYouNeedIt")
  141. }
  142. return next(ctx)
  143. }
  144. })
  145. app.GET("/", func(ctx echo.Context) error {
  146. if hub := sentryecho.GetHubFromContext(ctx); hub != nil {
  147. hub.WithScope(func(scope *sentry.Scope) {
  148. scope.SetExtra("unwantedQuery", "someQueryDataMaybe")
  149. hub.CaptureMessage("User provided unwanted query string, but we recovered just fine")
  150. })
  151. }
  152. return ctx.String(http.StatusOK, "Hello, World!")
  153. })
  154. app.GET("/foo", func(ctx echo.Context) error {
  155. // sentryecho handler will catch it just fine. Also, because we attached "someRandomTag"
  156. // in the middleware before, it will be sent through as well
  157. panic("y tho")
  158. })
  159. app.Logger.Fatal(app.Start(":3000"))
  160. `,
  161. },
  162. {
  163. description: (
  164. <strong>
  165. {tct('Accessing Request in [beforeSendCode:BeforeSend] callback', {
  166. beforeSendCode: <code />,
  167. })}
  168. </strong>
  169. ),
  170. language: 'go',
  171. code: `
  172. sentry.Init(sentry.ClientOptions{
  173. Dsn: "${dsn}",
  174. BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
  175. if hint.Context != nil {
  176. if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
  177. // You have access to the original Request here
  178. }
  179. }
  180. return event
  181. },
  182. })
  183. `,
  184. },
  185. ],
  186. },
  187. ];
  188. // Configuration End
  189. export function GettingStartedWithEcho({dsn, ...props}: ModuleProps) {
  190. return <Layout steps={steps({dsn})} {...props} />;
  191. }
  192. export default GettingStartedWithEcho;
  193. const AlertWithoutMarginBottom = styled(Alert)`
  194. margin-bottom: 0;
  195. `;