采样错误事件
要向 Sentry 发送一个具有代表性的错误样本, 请将 SDK 配置中的 SampleRate
选项设置为0
(发送了 0% 的错误)和1
(发送了 100% 的错误)之间的数字。这是一个静态速率,它同样适用于所有错误。例如,对 25% 的错误进行抽样:
注意:误差采样率不是动态的;更改它需要重新部署。此外,设置SDK示例速率会限制对事件源的可见性。为您的项目设置速率限制(仅在容量大时降低事件)可能更适合您的需要。
Shutdown and Draining
大多数 SDK 的默认行为是在后台通过网络异步发送事件。这意味着如果应用程序意外关闭,可能会丢失一些事件。SDK 提供了处理这种情况的机制。
为避免程序终止时意外删除事件,请安排 sentry.Flush
进行调用,通常使用 defer
。
如果您使用多个客户端,请安排每个相应的客户端刷新。
Flush
会一直等到任何缓冲事件发送到 Sentry 服务器,直到最多阻塞给定的超时时间。如果超时,则返回 false
。在这种情况下,某些事件可能尚未发送。
func main() { // err := sentry.Init(...) defer sentry.Flush(2 * time.Second) sentry.CaptureMessage("my message") }
Serverless
Source Context
sentry-go
SDK 附带了对 Serverless 解决方案的支持。但是,为了正确使用源上下文,您需要将源代码与二进制文件本身捆绑在一起。
例如,当使用 AWS Lambda 并给出这个树结构时:
. ├── bin │ └── upload-image │ └── process-image │ └── create-thumbnails ├── functions │ └── upload-image │ └── main.go │ └── process-image │ └── main.go │ └── create-thumbnails │ └── main.go ├── helper │ ├── foo.go │ └── bar.go ├── util │ ├── baz.go │ └── qux.go
您可以使用以下命令构建二进制文件之一并将其与必要的源文件捆绑在一起:
GOOS=linux go build -o bin/upload-image functions/upload-image/main.go && zip -r handler.zip bin/upload-image functions/upload-image/ helper/ util/
唯一的要求是您在已部署的计算机上找到源代码。SDK 会自动完成其他所有操作。
Events Delivery
大多数(如果不是全部)无服务器解决方案在关闭进程之前不会等待网络响应。因此,我们需要确保将事件传递给 Sentry 的服务器。
可以使用 sentry.Flush
方法或通过将传输交换到 HTTPSyncTransport
来实现双重目的。
用法
Sentry 的 SDK 挂接到您的运行时环境中,并自动报告错误,异常和拒绝。
关键术语:
- 事件是向 Sentry 发送数据的一个实例。通常,此数据是错误或异常。
- 一个问题是一组相似的事件。
- 事件的报告称为捕获。当一个事件被捕获,它被发送到 Sentry。
捕获的最常见形式是捕获错误。可以捕获为错误的内容因平台而异。通常,如果您有看起来像异常的东西,则可以将其捕获。对于某些 SDK,您还可以省略 capture_exception
的参数,Sentry 将尝试捕获当前异常。手动将错误或消息报告给 Sentry 也很有用。
除了捕获之外,您还可以记录导致事件的面包屑。面包屑与事件不同:它们不会在 Sentry 中创建事件,但将被缓冲直到发送下一个事件。在我们的面包屑文档中了解有关面包屑的更多信息。
捕获错误
要在 Go 中捕获事件,可以将实现 error
接口的任何结构传递给 CaptureException()
。如果使用第三方库而不是原生 errors
包,我们将尽力提取堆栈跟踪。
SDK完全兼容(但不限于):
- github.com/pkg/errors
- github.com/go-errors/errors
- github.com/pingcap/errors
如果有无法立即使用的错误包,请告诉我们!
f, err := os.Open("filename.ext") if err != nil { sentry.CaptureException(err) }
捕获消息
另一个常见的操作是捕获一条纯消息。消息是应该发送给 Sentry 的文本信息。通常情况下,消息不会被发出,但是对于某些团队来说,它们可能是有用的。
sentry.CaptureMessage("Something went wrong")
默认情况下,Sentry 的 Go SDK 使用异步传输。这意味着对 CaptureException
,CaptureEvent
和 CaptureMessage
的调用无需等待网络操作即可返回。而是在后台 goroutine 中缓冲事件并通过网络发送事件。调用 sentry.Flush
以等待事件传递,然后程序终止。您可以使用其他传输方式(例如 HTTPSyncTransport
)来更改默认行为。在 Transports 部分中有更多详细信息。
设置级别
级别 — 类似于日志级别 — 通常是基于集成默认添加的。您还可以在事件中覆盖它。
sentry.ConfigureScope(func(scope *sentry.Scope) { scope.SetLevel(sentry.LevelWarning) })
迁移指南
如何从 raven-go
转到 sentry-go
安装
raven-go
go get github.com/getsentry/raven-go
sentry-go
go get github.com/getsentry/sentry-go
配置
raven-go
import "github.com/getsentry/raven-go" func main() { raven.SetDSN("https://examplePublicKey@o0.ingest.sentry.io/0") }
sentry-go
import ( "fmt" "github.com/getsentry/sentry-go" ) func main() { err := sentry.Init(sentry.ClientOptions{ Dsn: "https://examplePublicKey@o0.ingest.sentry.io/0", }) if err != nil { fmt.Printf("Sentry initialization failed: %v\n", err) } }
raven-go
SetDSN() SetDefaultLoggerName() SetDebug() SetEnvironment() SetRelease() SetSampleRate() SetIgnoreErrors() SetIncludePaths()
sentry-go
sentry.Init(sentry.ClientOptions{ Dsn: "https://examplePublicKey@o0.ingest.sentry.io/0", DebugWriter: os.Stderr, Debug: true, Environment: "environment", Release: "release", SampleRate: 0.5, // IgnoreErrors: TBD, // IncludePaths: TBD })
可用选项:请参阅配置部分。
提供 SSL 证书
默认情况下,TLS 使用主机的根 CA 设置。如果您没有 ca-certificates
(这应该是解决丢失证书问题的首选方法),而要使用 gocertifi, 则可以提供预加载的证书文件作为 sentry.Init
调用的选项之一:
package main import ( "log" "github.com/certifi/gocertifi" "github.com/getsentry/sentry-go" ) sentryClientOptions := sentry.ClientOptions{ Dsn: "https://examplePublicKey@o0.ingest.sentry.io/0", } rootCAs, err := gocertifi.CACerts() if err != nil { log.Println("Couldn't load CA Certificates: %v\n", err) } else { sentryClientOptions.CaCerts = rootCAs } sentry.Init(sentryClientOptions)
用法
Capturing Errors
raven-go
f, err := os.Open("filename.ext") if err != nil { raven.CaptureError(err, nil) }
sentry-go
f, err := os.Open("filename.ext") if err != nil { sentry.CaptureException(err) }
Capturing Panics
raven-go
raven.CapturePanic(func() { // do all of the scary things here }, nil)
sentry-go
func() { defer sentry.Recover() // do all of the scary things here }()
Capturing Messages
raven-go
raven.CaptureMessage("Something bad happened and I would like to know about that")
sentry-go
sentry.CaptureMessage("Something bad happened and I would like to know about that")
Capturing Events
raven-go
packet := &raven.Packet{ Message: "Hand-crafted event", Extra: &raven.Extra{ "runtime.Version": runtime.Version(), "runtime.NumCPU": runtime.NumCPU(), }, } raven.Capture(packet)
sentry-go
event := sentry.NewEvent() event.Message = "Hand-crafted event" event.Extra["runtime.Version"] = runtime.Version() event.Extra["runtime.NumCPU"] = runtime.NumCPU() sentry.CaptureEvent(event)
Additional Data
See Context section.
Event Sampling
raven-go
raven.SetSampleRate(0.25)
sentry-go
sentry.Init(sentry.ClientOptions{ SampleRate: 0.25, })
Awaiting the response (not recommended)
raven.CaptureMessageAndWait("Something bad happened and I would like to know about that")
sentry-go
sentry.CaptureMessage("Something bad happened and I would like to know about that") if sentry.Flush(time.Second * 2) { // event delivered } else { // timeout reached }
Context
Per-event
raven-go
raven.CaptureError(err, map[string]string{"browser": "Firefox"}, &raven.Http{ Method: "GET", URL: "https://example.com/raven-go" })
sentry-go
sentry.WithScope(func(scope *sentry.Scope) { scope.SetTag("browser", "Firefox") scope.SetContext("Request", map[string]string{ "Method": "GET", "URL": "https://example.com/raven-go", }) sentry.CaptureException(err) })
Globally
SetHttpContext
raven-go
raven.SetHttpContext(&raven.Http{ Method: "GET", URL: "https://example.com/raven-go", })
sentry-go
sentry.ConfigureScope(func(scope *sentry.Scope) { scope.SetContext("Request", map[string]string{ "Method": "GET", "URL": "https://example.com/raven-go", }) })
SetTagsContext
raven-go
t := map[string]string{"day": "Friday", "sport": "Weightlifting"} raven.SetTagsContext(map[string]string{"day": "Friday", "sport": "Weightlifting"})
sentry-go
sentry.ConfigureScope(func(scope *sentry.Scope) { scope.SetTags(map[string]string{"day": "Friday", "sport": "Weightlifting"}) })
SetUserContext
raven-go
raven.SetUserContext(&raven.User{ ID: "1337", Username: "kamilogorek", Email: "kamil@sentry.io", IP: "127.0.0.1", })
sentry-go
sentry.ConfigureScope(func(scope *sentry.Scope) { scope.SetUser(sentry.User{ ID: "1337", Username: "kamilogorek", Email: "kamil@sentry.io", IPAddress: "127.0.0.1", }) })
ClearContext
raven-go
raven.ClearContext()
sentry-go
sentry.ConfigureScope(func(scope *sentry.Scope) { scope.Clear() })
WrapWithExtra
raven-go
path := "filename.ext" f, err := os.Open(path) if err != nil { err = raven.WrapWithExtra(err, map[string]string{"path": path, "cwd": os.Getwd()}) raven.CaptureError(err, nil) }
sentry-go
// use `sentry.WithScope`, see "Context / Per-event Section" path := "filename.ext" f, err := os.Open(path) if err != nil { sentry.WithScope(func(scope *sentry.Scope) { scope.SetExtras(map[string]interface{}{"path": path, "cwd": os.Getwd()}) sentry.CaptureException(err) }) }
Integrations
net/http
raven-go
mux := http.NewServeMux http.Handle("/", raven.Recoverer(mux)) // or func root(w http.ResponseWriter, r *http.Request) {} http.HandleFunc("/", raven.RecoveryHandler(root))
sentry-go
go get github.com/getsentry/sentry-go/http
import sentryhttp "github.com/getsentry/sentry-go/http" sentryHandler := sentryhttp.New(sentryhttp.Options{ Repanic: false, WaitForDelivery: true, }) mux := http.NewServeMux http.Handle("/", sentryHandler.Handle(mux)) // or func root(w http.ResponseWriter, r *http.Request) {} http.HandleFunc("/", sentryHandler.HandleFunc(root))