https://mattermost.atlassian.net/browse/MM-27613
Этот коммит содержится в:
Agniva De Sarker
2020-09-03 10:00:12 +05:30
коммит произвёл GitHub
родитель 54f86e7fb1
Коммит f2a8e10216
204 изменённых файлов: 14517 добавлений и 11770 удалений

10
vendor/github.com/getsentry/sentry-go/.golangci.yml сгенерированный поставляемый
Просмотреть файл

@@ -7,11 +7,11 @@ linters:
- dogsled
- dupl
- errcheck
- gochecknoglobals
- gochecknoinits
- goconst
- gocritic
- gocyclo
- godot
- gofmt
- goimports
- golint
@@ -33,14 +33,8 @@ linters:
- unparam
- unused
- varcheck
run:
skip-dirs:
- echo
- example/echo
- whitespace
issues:
exclude:
- "not declared by package utf8"
- "unicode/utf8/utf8.go"
exclude-rules:
- path: _test\.go
linters:

3
vendor/github.com/getsentry/sentry-go/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -24,10 +24,11 @@ jobs:
go test ./... -race
allow_failures:
- go: master
- env: GO111MODULE=off
fast_finish: true
before_install:
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/v1.19.1/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.19.1
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/v1.27.0/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.27.0
# Fetch origin/master. This is required for `git merge-base` when testing a
# branch, since Travis clones only the target branch.
- git fetch origin master:remotes/origin/master

28
vendor/github.com/getsentry/sentry-go/CHANGELOG.md сгенерированный поставляемый
Просмотреть файл

@@ -1,8 +1,32 @@
# Changelog
## Unreleased
## v0.7.0
- "I am running away from my responsibilities. And it feels good." – Michael Scott, Season 4, "Money"
- feat: Include original error when event cannot be encoded as JSON (#258)
- feat: Use Hub from request context when available (#217, #259)
- feat: Extract stack frames from golang.org/x/xerrors (#262)
- feat: Make Environment Integration preserve existing context data (#261)
- feat: Recover and RecoverWithContext with arbitrary types (#268)
- feat: Report bad usage of CaptureMessage and CaptureEvent (#269)
- feat: Send debug logging to stderr by default (#266)
- feat: Several improvements to documentation (#223, #245, #250, #265)
- feat: Example of Recover followed by panic (#241, #247)
- feat: Add Transactions and Spans (to support OpenTelemetry Sentry Exporter) (#235, #243, #254)
- fix: Set either Frame.Filename or Frame.AbsPath (#233)
- fix: Clone requestBody to new Scope (#244)
- fix: Synchronize access and mutation of Hub.lastEventID (#264)
- fix: Avoid repeated syscalls in prepareEvent (#256)
- fix: Do not allocate new RNG for every event (#256)
- fix: Remove stale replace directive in go.mod (#255)
- fix(http): Deprecate HandleFunc, remove duplication (#260)
_NOTE:_
This version comes packed with several fixes and improvements and no breaking
changes.
Notably, there is a change in how the SDK reports file names in stack traces
that should resolve any ambiguity when looking at stack traces and using the
Suspect Commits feature.
We recommend all users to upgrade.
## v0.6.1

59
vendor/github.com/getsentry/sentry-go/CONTRIBUTING.md сгенерированный поставляемый
Просмотреть файл

@@ -1,3 +1,45 @@
# Contributing to sentry-go
Hey, thank you if you're reading this, we welcome your contribution!
## Sending a Pull Request
Please help us save time when reviewing your PR by following this simple
process:
1. Is your PR a simple typo fix? Read no further, **click that green "Create
pull request" button**!
2. For more complex PRs that involve behavior changes or new APIs, please
consider [opening an **issue**][new-issue] describing the problem you're
trying to solve if there's not one already.
A PR is often one specific solution to a problem and sometimes talking about
the problem unfolds new possible solutions. Remember we will be responsible
for maintaining the changes later.
3. Fixing a bug and changing a behavior? Please add automated tests to prevent
future regression.
4. Practice writing good commit messages. We have [commit
guidelines][commit-guide].
5. We have [guidelines for PR submitters][pr-guide]. A short summary:
- Good PR descriptions are very helpful and most of the time they include
**why** something is done and why done in this particular way. Also list
other possible solutions that were considered and discarded.
- Be your own first reviewer. Make sure your code compiles and passes the
existing tests.
[new-issue]: https://github.com/getsentry/sentry-go/issues/new/choose
[commit-guide]: https://develop.sentry.dev/code-review/#commit-guidelines
[pr-guide]: https://develop.sentry.dev/code-review/#guidelines-for-submitters
Please also read through our [SDK Development docs](https://develop.sentry.dev/sdk/).
It contains information about SDK features, expected payloads and best practices for
contributing to Sentry SDKs.
## Community
The public-facing channels for support and development of Sentry SDKs can be found on [Discord](https://discord.gg/Ww9hbqr).
@@ -23,6 +65,7 @@ $ go test -race
```
### Coverage
```console
$ go test -race -coverprofile=coverage.txt -covermode=atomic && go tool cover -html coverage.txt
```
@@ -37,17 +80,17 @@ $ golangci-lint run
1. Update `CHANGELOG.md` with new version in `vX.X.X` format title and list of changes.
The command below can be used to get a list of changes since the last tag, with the format used in `CHANGELOG.md`:
The command below can be used to get a list of changes since the last tag, with the format used in `CHANGELOG.md`:
```console
$ git log --no-merges --format=%s $(git describe --abbrev=0).. | sed 's/^/- /'
```
```console
$ git log --no-merges --format=%s $(git describe --abbrev=0).. | sed 's/^/- /'
```
2. Commit with `misc: vX.X.X changelog` commit message and push to `master`.
3. Let [`craft`](https://github.com/getsentry/craft) do the rest:
```console
$ craft prepare X.X.X
$ craft publish X.X.X
```
```console
$ craft prepare X.X.X
$ craft publish X.X.X
```

2
vendor/github.com/getsentry/sentry-go/README.md сгенерированный поставляемый
Просмотреть файл

@@ -154,7 +154,7 @@ checkout the official documentation:
- [Configuration](https://docs.sentry.io/platforms/go/config)
- [Error Reporting](https://docs.sentry.io/error-reporting/quickstart?platform=go)
- [Enriching Error Data](https://docs.sentry.io/enriching-error-data/context?platform=go)
- [Enriching Error Data](https://docs.sentry.io/enriching-error-data/additional-data/?platform=go)
- [Transports](https://docs.sentry.io/platforms/go/transports)
- [Integrations](https://docs.sentry.io/platforms/go/integrations)
- [net/http](https://docs.sentry.io/platforms/go/http)

175
vendor/github.com/getsentry/sentry-go/client.go сгенерированный поставляемый
Просмотреть файл

@@ -12,6 +12,7 @@ import (
"os"
"reflect"
"sort"
"sync"
"time"
)
@@ -24,6 +25,40 @@ import (
// stack trace is often the most useful information.
const maxErrorDepth = 10
// hostname is the host name reported by the kernel. It is precomputed once to
// avoid syscalls when capturing events.
//
// The error is ignored because retrieving the host name is best-effort. If the
// error is non-nil, there is nothing to do other than retrying. We choose not
// to retry for now.
var hostname, _ = os.Hostname()
// lockedRand is a random number generator safe for concurrent use. Its API is
// intentionally limited and it is not meant as a full replacement for a
// rand.Rand.
type lockedRand struct {
mu sync.Mutex
r *rand.Rand
}
// Float64 returns a pseudo-random number in [0.0,1.0).
func (r *lockedRand) Float64() float64 {
r.mu.Lock()
defer r.mu.Unlock()
return r.r.Float64()
}
// rng is the internal random number generator.
//
// We do not use the global functions from math/rand because, while they are
// safe for concurrent use, any package in a build could change the seed and
// affect the generated numbers, for instance making them deterministic. On the
// other hand, the source returned from rand.NewSource is not safe for
// concurrent use, so we need to couple its use with a sync.Mutex.
var rng = &lockedRand{
r: rand.New(rand.NewSource(time.Now().UnixNano())),
}
// usageError is used to report to Sentry an SDK usage error.
//
// It is not exported because it is never returned by any function or method in
@@ -33,17 +68,27 @@ type usageError struct {
}
// Logger is an instance of log.Logger that is use to provide debug information about running Sentry Client
// can be enabled by either using `Logger.SetOutput` directly or with `Debug` client option
var Logger = log.New(ioutil.Discard, "[Sentry] ", log.LstdFlags) //nolint: gochecknoglobals
// can be enabled by either using Logger.SetOutput directly or with Debug client option.
var Logger = log.New(ioutil.Discard, "[Sentry] ", log.LstdFlags)
// EventProcessor is a function that processes an event.
// Event processors are used to change an event before it is sent to Sentry.
type EventProcessor func(event *Event, hint *EventHint) *Event
// EventModifier is the interface that wraps the ApplyToEvent method.
//
// ApplyToEvent changes an event based on external data and/or
// an event hint.
type EventModifier interface {
ApplyToEvent(event *Event, hint *EventHint) *Event
}
var globalEventProcessors []EventProcessor //nolint: gochecknoglobals
var globalEventProcessors []EventProcessor
// AddGlobalEventProcessor adds processor to the global list of event
// processors. Global event processors apply to all events.
//
// Deprecated: Use Scope.AddEventProcessor or Client.AddEventProcessor instead.
func AddGlobalEventProcessor(processor EventProcessor) {
globalEventProcessors = append(globalEventProcessors, processor)
}
@@ -54,14 +99,16 @@ type Integration interface {
SetupOnce(client *Client)
}
// ClientOptions that configures a SDK Client
// ClientOptions that configures a SDK Client.
type ClientOptions struct {
// The DSN to use. If the DSN is not set, the client is effectively disabled.
// The DSN to use. If the DSN is not set, the client is effectively
// disabled.
Dsn string
// In debug mode, the debug information is printed to stdout to help you understand what
// sentry is doing.
// In debug mode, the debug information is printed to stdout to help you
// understand what sentry is doing.
Debug bool
// Configures whether SDK should generate and attach stacktraces to pure capture message calls.
// Configures whether SDK should generate and attach stacktraces to pure
// capture message calls.
AttachStacktrace bool
// The sample rate for event submission (0.0 - 1.0, defaults to 1.0).
SampleRate float64
@@ -73,13 +120,12 @@ type ClientOptions struct {
BeforeSend func(event *Event, hint *EventHint) *Event
// Before breadcrumb add callback.
BeforeBreadcrumb func(breadcrumb *Breadcrumb, hint *BreadcrumbHint) *Breadcrumb
// Integrations to be installed on the current Client, receives default integrations
// Integrations to be installed on the current Client, receives default
// integrations.
Integrations func([]Integration) []Integration
// io.Writer implementation that should be used with the `Debug` mode
// io.Writer implementation that should be used with the Debug mode.
DebugWriter io.Writer
// The transport to use.
// This is an instance of a struct implementing `Transport` interface.
// Defaults to `httpTransport` from `transport.go`
// The transport to use. Defaults to HTTPTransport.
Transport Transport
// The server name to be reported.
ServerName string
@@ -91,26 +137,27 @@ type ClientOptions struct {
Environment string
// Maximum number of breadcrumbs.
MaxBreadcrumbs int
// An optional pointer to `http.Client` that will be used with a default HTTPTransport.
// Using your own client will make HTTPTransport, HTTPProxy, HTTPSProxy and CaCerts options ignored.
// An optional pointer to http.Client that will be used with a default
// HTTPTransport. Using your own client will make HTTPTransport, HTTPProxy,
// HTTPSProxy and CaCerts options ignored.
HTTPClient *http.Client
// An optional pointer to `http.Transport` that will be used with a default HTTPTransport.
// Using your own transport will make HTTPProxy, HTTPSProxy and CaCerts options ignored.
// An optional pointer to http.Transport that will be used with a default
// HTTPTransport. Using your own transport will make HTTPProxy, HTTPSProxy
// and CaCerts options ignored.
HTTPTransport http.RoundTripper
// An optional HTTP proxy to use.
// This will default to the `http_proxy` environment variable.
// or `https_proxy` if that one exists.
// This will default to the HTTP_PROXY environment variable.
HTTPProxy string
// An optional HTTPS proxy to use.
// This will default to the `HTTPS_PROXY` environment variable
// or `http_proxy` if that one exists.
// This will default to the HTTPS_PROXY environment variable.
// HTTPS_PROXY takes precedence over HTTP_PROXY for https requests.
HTTPSProxy string
// An optional CaCerts to use.
// Defaults to `gocertifi.CACerts()`.
// An optional set of SSL certificates to use.
CaCerts *x509.CertPool
}
// Client is the underlying processor that's used by the main API and `Hub` instances.
// Client is the underlying processor that is used by the main API and Hub
// instances.
type Client struct {
options ClientOptions
dsn *Dsn
@@ -119,12 +166,12 @@ type Client struct {
Transport Transport
}
// NewClient creates and returns an instance of `Client` configured using `ClientOptions`.
// NewClient creates and returns an instance of Client configured using ClientOptions.
func NewClient(options ClientOptions) (*Client, error) {
if options.Debug {
debugWriter := options.DebugWriter
if debugWriter == nil {
debugWriter = os.Stdout
debugWriter = os.Stderr
}
Logger.SetOutput(debugWriter)
}
@@ -204,7 +251,7 @@ func (client *Client) AddEventProcessor(processor EventProcessor) {
client.eventProcessors = append(client.eventProcessors, processor)
}
// Options return `ClientOptions` for the current `Client`.
// Options return ClientOptions for the current Client.
func (client Client) Options() ClientOptions {
return client.options
}
@@ -224,36 +271,29 @@ func (client *Client) CaptureException(exception error, hint *EventHint, scope E
// CaptureEvent captures an event on the currently active client if any.
//
// The event must already be assembled. Typically code would instead use
// the utility methods like `CaptureException`. The return value is the
// the utility methods like CaptureException. The return value is the
// event ID. In case Sentry is disabled or event was dropped, the return value will be nil.
func (client *Client) CaptureEvent(event *Event, hint *EventHint, scope EventModifier) *EventID {
return client.processEvent(event, hint, scope)
}
// Recover captures a panic.
// Returns `EventID` if successfully, or `nil` if there's no error to recover from.
// Returns EventID if successfully, or nil if there's no error to recover from.
func (client *Client) Recover(err interface{}, hint *EventHint, scope EventModifier) *EventID {
if err == nil {
err = recover()
}
if err != nil {
if err, ok := err.(error); ok {
event := client.eventFromException(err, LevelFatal)
return client.CaptureEvent(event, hint, scope)
}
if err, ok := err.(string); ok {
event := client.eventFromMessage(err, LevelFatal)
return client.CaptureEvent(event, hint, scope)
}
}
return nil
// Normally we would not pass a nil Context, but RecoverWithContext doesn't
// use the Context for communicating deadline nor cancelation. All it does
// is store the Context in the EventHint and there nil means the Context is
// not available.
//nolint: staticcheck
return client.RecoverWithContext(nil, err, hint, scope)
}
// Recover captures a panic and passes relevant context object.
// Returns `EventID` if successfully, or `nil` if there's no error to recover from.
// RecoverWithContext captures a panic and passes relevant context object.
// Returns EventID if successfully, or nil if there's no error to recover from.
func (client *Client) RecoverWithContext(
ctx context.Context,
err interface{},
@@ -263,24 +303,29 @@ func (client *Client) RecoverWithContext(
if err == nil {
err = recover()
}
if err == nil {
return nil
}
if err != nil {
if hint.Context == nil && ctx != nil {
if ctx != nil {
if hint == nil {
hint = &EventHint{}
}
if hint.Context == nil {
hint.Context = ctx
}
if err, ok := err.(error); ok {
event := client.eventFromException(err, LevelFatal)
return client.CaptureEvent(event, hint, scope)
}
if err, ok := err.(string); ok {
event := client.eventFromMessage(err, LevelFatal)
return client.CaptureEvent(event, hint, scope)
}
}
return nil
var event *Event
switch err := err.(type) {
case error:
event = client.eventFromException(err, LevelFatal)
case string:
event = client.eventFromMessage(err, LevelFatal)
default:
event = client.eventFromMessage(fmt.Sprintf("%#v", err), LevelFatal)
}
return client.CaptureEvent(event, hint, scope)
}
// Flush waits until the underlying Transport sends any buffered events to the
@@ -299,6 +344,10 @@ func (client *Client) Flush(timeout time.Duration) bool {
}
func (client *Client) eventFromMessage(message string, level Level) *Event {
if message == "" {
err := usageError{fmt.Errorf("%s called with empty message", callerFunctionName())}
return client.eventFromException(err, level)
}
event := NewEvent()
event.Level = level
event.Message = message
@@ -362,6 +411,11 @@ func reverse(a []Exception) {
}
func (client *Client) processEvent(event *Event, hint *EventHint, scope EventModifier) *EventID {
if event == nil {
err := usageError{fmt.Errorf("%s called with nil event", callerFunctionName())}
return client.CaptureException(err, hint, scope)
}
options := client.Options()
// TODO: Reconsider if its worth going away from default implementation
@@ -369,7 +423,7 @@ func (client *Client) processEvent(event *Event, hint *EventHint, scope EventMod
// which means that if someone uses ClientOptions{} struct directly
// and we would not check for 0 here, we'd skip all events by default
if options.SampleRate != 0.0 {
randomFloat := rand.New(rand.NewSource(time.Now().UnixNano())).Float64()
randomFloat := rng.Float64()
if randomFloat > options.SampleRate {
Logger.Println("Event dropped due to SampleRate hit.")
return nil
@@ -380,7 +434,8 @@ func (client *Client) processEvent(event *Event, hint *EventHint, scope EventMod
return nil
}
if options.BeforeSend != nil {
// As per spec, transactions do not go through BeforeSend.
if event.Type != transactionType && options.BeforeSend != nil {
h := &EventHint{}
if hint != nil {
h = hint
@@ -412,7 +467,7 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
if event.ServerName == "" {
if client.Options().ServerName != "" {
event.ServerName = client.Options().ServerName
} else if hostname, err := os.Hostname(); err == nil {
} else {
event.ServerName = hostname
}
}

38
vendor/github.com/getsentry/sentry-go/doc.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,38 @@
/*
Package sentry is the official Sentry SDK for Go.
For more information about Sentry and SDK features please have a look at the
documentation site https://docs.sentry.io/platforms/go/.
Basic Usage
The first step is to initialize the SDK, providing at a minimum the DSN of your
Sentry project. This step is accomplished through a call to sentry.Init.
func main() {
err := sentry.Init(...)
...
}
A more detailed yet simple example is available at
https://github.com/getsentry/sentry-go/blob/master/example/basic/main.go.
Integrations
The SDK has support for several Go frameworks, available as subpackages.
Getting Support
For paid Sentry.io accounts, head out to https://sentry.io/support.
For all users, support channels include:
Forum: https://forum.sentry.io
Discord: https://discord.gg/Ww9hbqr (#go channel)
If you found an issue with the SDK, please report through
https://github.com/getsentry/sentry-go/issues/new/choose.
For responsibly disclosing a security issue, please follow the steps in
https://sentry.io/security/#vulnerability-disclosure.
*/
package sentry

24
vendor/github.com/getsentry/sentry-go/dsn.go сгенерированный поставляемый
Просмотреть файл

@@ -27,6 +27,8 @@ func (scheme scheme) defaultPort() int {
}
}
// DsnParseError represents an error that occurs if a Sentry
// DSN cannot be parsed.
type DsnParseError struct {
Message string
}
@@ -46,7 +48,7 @@ type Dsn struct {
projectID int
}
// NewDsn creates an instance of `Dsn` by parsing provided url in a `string` format.
// NewDsn creates an instance of Dsn by parsing provided url in a string format.
// If Dsn is not set the client is effectively disabled.
func NewDsn(rawURL string) (*Dsn, error) {
// Parse
@@ -123,7 +125,7 @@ func NewDsn(rawURL string) (*Dsn, error) {
}, nil
}
// String formats Dsn struct into a valid string url
// String formats Dsn struct into a valid string url.
func (dsn Dsn) String() string {
var url string
url += fmt.Sprintf("%s://%s", dsn.scheme, dsn.publicKey)
@@ -141,9 +143,19 @@ func (dsn Dsn) String() string {
return url
}
// StoreAPIURL returns assembled url to be used in the transport.
// It points to configures Sentry instance.
// StoreAPIURL returns the URL of the store endpoint of the project associated
// with the DSN.
func (dsn Dsn) StoreAPIURL() *url.URL {
return dsn.getAPIURL("store")
}
// EnvelopeAPIURL returns the URL of the envelope endpoint of the project
// associated with the DSN.
func (dsn Dsn) EnvelopeAPIURL() *url.URL {
return dsn.getAPIURL("envelope")
}
func (dsn Dsn) getAPIURL(s string) *url.URL {
var rawURL string
rawURL += fmt.Sprintf("%s://%s", dsn.scheme, dsn.host)
if dsn.port != dsn.scheme.defaultPort() {
@@ -152,7 +164,7 @@ func (dsn Dsn) StoreAPIURL() *url.URL {
if dsn.path != "" {
rawURL += dsn.path
}
rawURL += fmt.Sprintf("/api/%d/store/", dsn.projectID)
rawURL += fmt.Sprintf("/api/%d/%s/", dsn.projectID, s)
parsedURL, _ := url.Parse(rawURL)
return parsedURL
}
@@ -172,10 +184,12 @@ func (dsn Dsn) RequestHeaders() map[string]string {
}
}
// MarshalJSON converts the Dsn struct to JSON.
func (dsn Dsn) MarshalJSON() ([]byte, error) {
return json.Marshal(dsn.String())
}
// UnmarshalJSON converts JSON data to the Dsn struct.
func (dsn *Dsn) UnmarshalJSON(data []byte) error {
var str string
_ = json.Unmarshal(data, &str)

2
vendor/github.com/getsentry/sentry-go/go.mod сгенерированный поставляемый
Просмотреть файл

@@ -31,5 +31,3 @@ require (
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
github.com/yudai/pp v2.0.1+incompatible // indirect
)
replace github.com/ugorji/go v1.1.4 => github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43

4
vendor/github.com/getsentry/sentry-go/go.sum сгенерированный поставляемый
Просмотреть файл

@@ -170,13 +170,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA=
github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=

34
vendor/github.com/getsentry/sentry-go/http/sentryhttp.go сгенерированный поставляемый
Просмотреть файл

@@ -50,32 +50,28 @@ func New(options Options) *Handler {
// Handle wraps http.Handler and recovers from caught panics.
func (h *Handler) Handle(handler http.Handler) http.Handler {
return h.handle(handler)
}
// Deprecated: Use the Handle method instead.
func (h *Handler) HandleFunc(handler http.HandlerFunc) http.HandlerFunc {
return h.handle(handler)
}
func (h *Handler) handle(handler http.Handler) http.HandlerFunc {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
hub := sentry.CurrentHub().Clone()
ctx := r.Context()
hub := sentry.GetHubFromContext(ctx)
if hub == nil {
hub = sentry.CurrentHub().Clone()
}
hub.Scope().SetRequest(r)
ctx := sentry.SetHubOnContext(
r.Context(),
hub,
)
ctx = sentry.SetHubOnContext(ctx, hub)
defer h.recoverWithSentry(hub, r)
handler.ServeHTTP(rw, r.WithContext(ctx))
})
}
// HandleFunc wraps http.HandleFunc and recovers from caught panics.
func (h *Handler) HandleFunc(handler http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, r *http.Request) {
hub := sentry.CurrentHub().Clone()
hub.Scope().SetRequest(r)
ctx := sentry.SetHubOnContext(
r.Context(),
hub,
)
defer h.recoverWithSentry(hub, r)
handler(rw, r.WithContext(ctx))
}
}
func (h *Handler) recoverWithSentry(hub *sentry.Hub, r *http.Request) {
if err := recover(); err != nil {
eventID := hub.RecoverWithContext(

115
vendor/github.com/getsentry/sentry-go/hub.go сгенерированный поставляемый
Просмотреть файл

@@ -8,21 +8,25 @@ import (
type contextKey int
// HubContextKey is a context key used to store Hub on any context.Context type
const HubContextKey = contextKey(1)
// Keys used to store values in a Context. Use with Context.Value to access
// values stored by the SDK.
const (
// HubContextKey is the key used to store the current Hub.
HubContextKey = contextKey(1)
// RequestContextKey is the key used to store the current http.Request.
RequestContextKey = contextKey(2)
)
// RequestContextKey is a context key used to store http.Request on the context passed to RecoverWithContext
const RequestContextKey = contextKey(2)
// Default maximum number of breadcrumbs added to an event. Can be overwritten `maxBreadcrumbs` option.
// defaultMaxBreadcrumbs is the default maximum number of breadcrumbs added to
// an event. Can be overwritten with the maxBreadcrumbs option.
const defaultMaxBreadcrumbs = 30
// Absolute maximum number of breadcrumbs added to an event.
// The `maxBreadcrumbs` option cannot be higher than this value.
// maxBreadcrumbs is the absolute maximum number of breadcrumbs added to an
// event. The maxBreadcrumbs option cannot be set higher than this value.
const maxBreadcrumbs = 100
// Initial instance of the Hub that has no `Client` bound and an empty `Scope`
var currentHub = NewHub(nil, NewScope()) //nolint: gochecknoglobals
// currentHub is the initial Hub with no Client bound and an empty Scope.
var currentHub = NewHub(nil, NewScope())
// Hub is the central object that manages scopes and clients.
//
@@ -31,7 +35,7 @@ var currentHub = NewHub(nil, NewScope()) //nolint: gochecknoglobals
//
// In most situations developers do not need to interface the hub. Instead
// toplevel convenience functions are exposed that will automatically dispatch
// to global (`CurrentHub`) hub. In some situations this might not be
// to global (CurrentHub) hub. In some situations this might not be
// possible in which case it might become necessary to manually work with the
// hub. This is for instance the case when working with async code.
type Hub struct {
@@ -64,7 +68,7 @@ func (l *layer) SetClient(c *Client) {
type stack []*layer
// NewHub returns an instance of a `Hub` with provided `Client` and `Scope` bound.
// NewHub returns an instance of a Hub with provided Client and Scope bound.
func NewHub(client *Client, scope *Scope) *Hub {
hub := Hub{
stack: &stack{{
@@ -75,13 +79,16 @@ func NewHub(client *Client, scope *Scope) *Hub {
return &hub
}
// CurrentHub returns an instance of previously initialized `Hub` stored in the global namespace.
// CurrentHub returns an instance of previously initialized Hub stored in the global namespace.
func CurrentHub() *Hub {
return currentHub
}
// LastEventID returns an ID of last captured event for the current `Hub`.
// LastEventID returns an ID of last captured event for the current Hub.
func (hub *Hub) LastEventID() EventID {
hub.mu.RLock()
defer hub.mu.RUnlock()
return hub.lastEventID
}
@@ -116,7 +123,7 @@ func (hub *Hub) Clone() *Hub {
return NewHub(top.Client(), scope)
}
// Scope returns top-level `Scope` of the current `Hub` or `nil` if no `Scope` is bound.
// Scope returns top-level Scope of the current Hub or nil if no Scope is bound.
func (hub *Hub) Scope() *Scope {
top := hub.stackTop()
if top == nil {
@@ -125,7 +132,7 @@ func (hub *Hub) Scope() *Scope {
return top.scope
}
// Scope returns top-level `Client` of the current `Hub` or `nil` if no `Client` is bound.
// Client returns top-level Client of the current Hub or nil if no Client is bound.
func (hub *Hub) Client() *Client {
top := hub.stackTop()
if top == nil {
@@ -134,7 +141,7 @@ func (hub *Hub) Client() *Client {
return top.Client()
}
// PushScope pushes a new scope for the current `Hub` and reuses previously bound `Client`.
// PushScope pushes a new scope for the current Hub and reuses previously bound Client.
func (hub *Hub) PushScope() *Scope {
top := hub.stackTop()
@@ -161,7 +168,7 @@ func (hub *Hub) PushScope() *Scope {
return scope
}
// PushScope pops the most recent scope for the current `Hub`.
// PopScope pops the most recent scope for the current Hub.
func (hub *Hub) PopScope() {
hub.mu.Lock()
defer hub.mu.Unlock()
@@ -173,7 +180,7 @@ func (hub *Hub) PopScope() {
}
}
// BindClient binds a new `Client` for the current `Hub`.
// BindClient binds a new Client for the current Hub.
func (hub *Hub) BindClient(client *Client) {
top := hub.stackTop()
if top != nil {
@@ -181,36 +188,46 @@ func (hub *Hub) BindClient(client *Client) {
}
}
// WithScope temporarily pushes a scope for a single call.
// WithScope runs f in an isolated temporary scope.
//
// A shorthand for:
// PushScope()
// f(scope)
// PopScope()
// It is useful when extra data should be sent with a single capture call, for
// instance a different level or tags.
//
// The scope passed to f starts as a clone of the current scope and can be
// freely modified without affecting the current scope.
//
// It is a shorthand for PushScope followed by PopScope.
func (hub *Hub) WithScope(f func(scope *Scope)) {
scope := hub.PushScope()
defer hub.PopScope()
f(scope)
}
// ConfigureScope invokes a function that can modify the current scope.
// ConfigureScope runs f in the current scope.
//
// The function is passed a mutable reference to the `Scope` so that modifications
// can be performed.
// It is useful to set data that applies to all events that share the current
// scope.
//
// Modifying the scope affects all references to the current scope.
//
// See also WithScope for making isolated temporary changes.
func (hub *Hub) ConfigureScope(f func(scope *Scope)) {
scope := hub.Scope()
f(scope)
}
// CaptureEvent calls the method of a same name on currently bound `Client` instance
// passing it a top-level `Scope`.
// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available.
// CaptureEvent calls the method of a same name on currently bound Client instance
// passing it a top-level Scope.
// Returns EventID if successfully, or nil if there's no Scope or Client available.
func (hub *Hub) CaptureEvent(event *Event) *EventID {
client, scope := hub.Client(), hub.Scope()
if client == nil || scope == nil {
return nil
}
eventID := client.CaptureEvent(event, nil, scope)
hub.mu.Lock()
defer hub.mu.Unlock()
if eventID != nil {
hub.lastEventID = *eventID
} else {
@@ -219,15 +236,18 @@ func (hub *Hub) CaptureEvent(event *Event) *EventID {
return eventID
}
// CaptureMessage calls the method of a same name on currently bound `Client` instance
// passing it a top-level `Scope`.
// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available.
// CaptureMessage calls the method of a same name on currently bound Client instance
// passing it a top-level Scope.
// Returns EventID if successfully, or nil if there's no Scope or Client available.
func (hub *Hub) CaptureMessage(message string) *EventID {
client, scope := hub.Client(), hub.Scope()
if client == nil || scope == nil {
return nil
}
eventID := client.CaptureMessage(message, nil, scope)
hub.mu.Lock()
defer hub.mu.Unlock()
if eventID != nil {
hub.lastEventID = *eventID
} else {
@@ -236,15 +256,18 @@ func (hub *Hub) CaptureMessage(message string) *EventID {
return eventID
}
// CaptureException calls the method of a same name on currently bound `Client` instance
// passing it a top-level `Scope`.
// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available.
// CaptureException calls the method of a same name on currently bound Client instance
// passing it a top-level Scope.
// Returns EventID if successfully, or nil if there's no Scope or Client available.
func (hub *Hub) CaptureException(exception error) *EventID {
client, scope := hub.Client(), hub.Scope()
if client == nil || scope == nil {
return nil
}
eventID := client.CaptureException(exception, &EventHint{OriginalException: exception}, scope)
hub.mu.Lock()
defer hub.mu.Unlock()
if eventID != nil {
hub.lastEventID = *eventID
} else {
@@ -294,9 +317,9 @@ func (hub *Hub) AddBreadcrumb(breadcrumb *Breadcrumb, hint *BreadcrumbHint) {
hub.Scope().AddBreadcrumb(breadcrumb, max)
}
// Recover calls the method of a same name on currently bound `Client` instance
// passing it a top-level `Scope`.
// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available.
// Recover calls the method of a same name on currently bound Client instance
// passing it a top-level Scope.
// Returns EventID if successfully, or nil if there's no Scope or Client available.
func (hub *Hub) Recover(err interface{}) *EventID {
if err == nil {
err = recover()
@@ -308,9 +331,9 @@ func (hub *Hub) Recover(err interface{}) *EventID {
return client.Recover(err, &EventHint{RecoveredException: err}, scope)
}
// RecoverWithContext calls the method of a same name on currently bound `Client` instance
// passing it a top-level `Scope`.
// Returns `EventID` if successfully, or `nil` if there's no `Scope` or `Client` available.
// RecoverWithContext calls the method of a same name on currently bound Client instance
// passing it a top-level Scope.
// Returns EventID if successfully, or nil if there's no Scope or Client available.
func (hub *Hub) RecoverWithContext(ctx context.Context, err interface{}) *EventID {
if err == nil {
err = recover()
@@ -343,14 +366,14 @@ func (hub *Hub) Flush(timeout time.Duration) bool {
return client.Flush(timeout)
}
// HasHubOnContext checks whether `Hub` instance is bound to a given `Context` struct.
// HasHubOnContext checks whether Hub instance is bound to a given Context struct.
func HasHubOnContext(ctx context.Context) bool {
_, ok := ctx.Value(HubContextKey).(*Hub)
return ok
}
// GetHubFromContext tries to retrieve `Hub` instance from the given `Context` struct
// or return `nil` if one is not found.
// GetHubFromContext tries to retrieve Hub instance from the given Context struct
// or return nil if one is not found.
func GetHubFromContext(ctx context.Context) *Hub {
if hub, ok := ctx.Value(HubContextKey).(*Hub); ok {
return hub
@@ -358,7 +381,7 @@ func GetHubFromContext(ctx context.Context) *Hub {
return nil
}
// SetHubOnContext stores given `Hub` instance on the `Context` struct and returns a new `Context`.
// SetHubOnContext stores given Hub instance on the Context struct and returns a new Context.
func SetHubOnContext(ctx context.Context, hub *Hub) context.Context {
return context.WithValue(ctx, HubContextKey, hub)
}

50
vendor/github.com/getsentry/sentry-go/integrations.go сгенерированный поставляемый
Просмотреть файл

@@ -70,27 +70,49 @@ func (ei *environmentIntegration) SetupOnce(client *Client) {
}
func (ei *environmentIntegration) processor(event *Event, hint *EventHint) *Event {
// Initialize maps as necessary.
if event.Contexts == nil {
event.Contexts = make(map[string]interface{})
}
event.Contexts["device"] = map[string]interface{}{
"arch": runtime.GOARCH,
"num_cpu": runtime.NumCPU(),
for _, name := range []string{"device", "os", "runtime"} {
if event.Contexts[name] == nil {
event.Contexts[name] = make(map[string]interface{})
}
}
event.Contexts["os"] = map[string]interface{}{
"name": runtime.GOOS,
// Set contextual information preserving existing data. For each context, if
// the existing value is not of type map[string]interface{}, then no
// additional information is added.
if deviceContext, ok := event.Contexts["device"].(map[string]interface{}); ok {
if _, ok := deviceContext["arch"]; !ok {
deviceContext["arch"] = runtime.GOARCH
}
if _, ok := deviceContext["num_cpu"]; !ok {
deviceContext["num_cpu"] = runtime.NumCPU()
}
}
event.Contexts["runtime"] = map[string]interface{}{
"name": "go",
"version": runtime.Version(),
"go_numroutines": runtime.NumGoroutine(),
"go_maxprocs": runtime.GOMAXPROCS(0),
"go_numcgocalls": runtime.NumCgoCall(),
if osContext, ok := event.Contexts["os"].(map[string]interface{}); ok {
if _, ok := osContext["name"]; !ok {
osContext["name"] = runtime.GOOS
}
}
if runtimeContext, ok := event.Contexts["runtime"].(map[string]interface{}); ok {
if _, ok := runtimeContext["name"]; !ok {
runtimeContext["name"] = "go"
}
if _, ok := runtimeContext["version"]; !ok {
runtimeContext["version"] = runtime.Version()
}
if _, ok := runtimeContext["go_numroutines"]; !ok {
runtimeContext["go_numroutines"] = runtime.NumGoroutine()
}
if _, ok := runtimeContext["go_maxprocs"]; !ok {
runtimeContext["go_maxprocs"] = runtime.GOMAXPROCS(0)
}
if _, ok := runtimeContext["go_numcgocalls"]; !ok {
runtimeContext["go_numcgocalls"] = runtime.NumCgoCall()
}
}
return event
}

126
vendor/github.com/getsentry/sentry-go/interfaces.go сгенерированный поставляемый
Просмотреть файл

@@ -13,9 +13,13 @@ import (
// Protocol Docs (kinda)
// https://github.com/getsentry/rust-sentry-types/blob/master/src/protocol/v7.rs
// Level marks the severity of the event
// transactionType is the type of a transaction event.
const transactionType = "transaction"
// Level marks the severity of the event.
type Level string
// Describes the severity of the event.
const (
LevelDebug Level = "debug"
LevelInfo Level = "info"
@@ -24,7 +28,7 @@ const (
LevelFatal Level = "fatal"
)
// https://docs.sentry.io/development/sdk-dev/event-payloads/sdk/
// SdkInfo contains all metadata about about the SDK being used.
type SdkInfo struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
@@ -32,6 +36,7 @@ type SdkInfo struct {
Packages []SdkPackage `json:"packages,omitempty"`
}
// SdkPackage describes a package that was installed.
type SdkPackage struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
@@ -39,10 +44,13 @@ type SdkPackage struct {
// TODO: This type could be more useful, as map of interface{} is too generic
// and requires a lot of type assertions in beforeBreadcrumb calls
// plus it could just be `map[string]interface{}` then
// plus it could just be map[string]interface{} then.
// BreadcrumbHint contains information that can be associated with a Breadcrumb.
type BreadcrumbHint map[string]interface{}
// https://docs.sentry.io/development/sdk-dev/event-payloads/breadcrumbs/
// Breadcrumb specifies an application event that occurred before a Sentry event.
// An event may contain one or more breadcrumbs.
type Breadcrumb struct {
Category string `json:"category,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
@@ -52,6 +60,7 @@ type Breadcrumb struct {
Type string `json:"type,omitempty"`
}
// MarshalJSON converts the Breadcrumb struct to JSON.
func (b *Breadcrumb) MarshalJSON() ([]byte, error) {
type alias Breadcrumb
// encoding/json doesn't support the "omitempty" option for struct types.
@@ -67,14 +76,11 @@ func (b *Breadcrumb) MarshalJSON() ([]byte, error) {
alias: (*alias)(b),
})
}
return json.Marshal(&struct {
*alias
}{
alias: (*alias)(b),
})
return json.Marshal((*alias)(b))
}
// https://docs.sentry.io/development/sdk-dev/event-payloads/user/
// User describes the user associated with an Event. If this is used, at least
// an ID or an IP address should be provided.
type User struct {
Email string `json:"email,omitempty"`
ID string `json:"id,omitempty"`
@@ -82,7 +88,7 @@ type User struct {
Username string `json:"username,omitempty"`
}
// https://docs.sentry.io/development/sdk-dev/event-payloads/request/
// Request contains information on a HTTP request related to the event.
type Request struct {
URL string `json:"url,omitempty"`
Method string `json:"method,omitempty"`
@@ -131,7 +137,7 @@ func NewRequest(r *http.Request) *Request {
}
}
// https://docs.sentry.io/development/sdk-dev/event-payloads/exception/
// Exception specifies an error that occurred.
type Exception struct {
Type string `json:"type,omitempty"`
Value string `json:"value,omitempty"`
@@ -141,9 +147,11 @@ type Exception struct {
RawStacktrace *Stacktrace `json:"raw_stacktrace,omitempty"`
}
// EventID is a hexadecimal string representing a unique uuid4 for an Event.
// An EventID must be 32 characters long, lowercase and not have any dashes.
type EventID string
// https://docs.sentry.io/development/sdk-dev/event-payloads/
// Event is the fundamental data structure that is sent to Sentry.
type Event struct {
Breadcrumbs []*Breadcrumb `json:"breadcrumbs,omitempty"`
Contexts map[string]interface{} `json:"contexts,omitempty"`
@@ -167,30 +175,57 @@ type Event struct {
Modules map[string]string `json:"modules,omitempty"`
Request *Request `json:"request,omitempty"`
Exception []Exception `json:"exception,omitempty"`
// Experimental: This is part of a beta feature of the SDK. The fields below
// are only relevant for transactions.
Type string `json:"type,omitempty"`
StartTimestamp time.Time `json:"start_timestamp"`
Spans []*Span `json:"spans,omitempty"`
}
// MarshalJSON converts the Event struct to JSON.
func (e *Event) MarshalJSON() ([]byte, error) {
type alias Event
// encoding/json doesn't support the "omitempty" option for struct types.
// See https://golang.org/issues/11939.
// This implementation of MarshalJSON shadows the original Timestamp field
// forcing it to be omitted when the Timestamp is the zero value of
// time.Time.
if e.Timestamp.IsZero() {
return json.Marshal(&struct {
*alias
Timestamp json.RawMessage `json:"timestamp,omitempty"`
}{
alias: (*alias)(e),
})
// event aliases Event to allow calling json.Marshal without an infinite
// loop. It preserves all fields of Event while none of the attached
// methods.
type event Event
// Transactions are marshaled in the standard way how json.Marshal works.
if e.Type == transactionType {
return json.Marshal((*event)(e))
}
return json.Marshal(&struct {
*alias
}{
alias: (*alias)(e),
})
// errorEvent is like Event with some shadowed fields for customizing the
// JSON serialization of regular "error events".
type errorEvent struct {
*event
// encoding/json doesn't support the omitempty option for struct types.
// See https://golang.org/issues/11939.
// We shadow the original Event.Timestamp field with a json.RawMessage.
// This allows us to include the timestamp when non-zero and omit it
// otherwise.
Timestamp json.RawMessage `json:"timestamp,omitempty"`
// The fields below are not part of the regular "error events" and only
// make sense to be sent for transactions. They shadow the respective
// fields in Event and are meant to remain nil, triggering the omitempty
// behavior.
Type json.RawMessage `json:"type,omitempty"`
StartTimestamp json.RawMessage `json:"start_timestamp,omitempty"`
Spans json.RawMessage `json:"spans,omitempty"`
}
x := &errorEvent{event: (*event)(e)}
if !e.Timestamp.IsZero() {
x.Timestamp = append(x.Timestamp, '"')
x.Timestamp = e.Timestamp.UTC().AppendFormat(x.Timestamp, time.RFC3339Nano)
x.Timestamp = append(x.Timestamp, '"')
}
return json.Marshal(x)
}
// NewEvent creates a new Event.
func NewEvent() *Event {
event := Event{
Contexts: make(map[string]interface{}),
@@ -201,6 +236,7 @@ func NewEvent() *Event {
return &event
}
// Thread specifies threads that were running at the time of an event.
type Thread struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
@@ -210,6 +246,7 @@ type Thread struct {
Current bool `json:"current,omitempty"`
}
// EventHint contains information that can be associated with an Event.
type EventHint struct {
Data interface{}
EventID string
@@ -219,3 +256,30 @@ type EventHint struct {
Request *http.Request
Response *http.Response
}
// TraceContext describes the context of the trace.
//
// Experimental: This is part of a beta feature of the SDK.
type TraceContext struct {
TraceID string `json:"trace_id"`
SpanID string `json:"span_id"`
Op string `json:"op,omitempty"`
Description string `json:"description,omitempty"`
Status string `json:"status,omitempty"`
}
// Span describes a timed unit of work in a trace.
//
// Experimental: This is part of a beta feature of the SDK.
type Span struct {
TraceID string `json:"trace_id"`
SpanID string `json:"span_id"`
ParentSpanID string `json:"parent_span_id,omitempty"`
Op string `json:"op,omitempty"`
Description string `json:"description,omitempty"`
Status string `json:"status,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
StartTimestamp time.Time `json:"start_timestamp"`
EndTimestamp time.Time `json:"timestamp"`
Data map[string]interface{} `json:"data,omitempty"`
}

21
vendor/github.com/getsentry/sentry-go/scope.go сгенерированный поставляемый
Просмотреть файл

@@ -11,19 +11,18 @@ import (
// Scope holds contextual data for the current scope.
//
// The scope is an object that can cloned efficiently and stores data that
// is locally relevant to an event. For instance the scope will hold recorded
// The scope is an object that can cloned efficiently and stores data that is
// locally relevant to an event. For instance the scope will hold recorded
// breadcrumbs and similar information.
//
// The scope can be interacted with in two ways:
// The scope can be interacted with in two ways. First, the scope is routinely
// updated with information by functions such as AddBreadcrumb which will modify
// the current scope. Second, the current scope can be configured through the
// ConfigureScope function or Hub method of the same name.
//
// 1. the scope is routinely updated with information by functions such as
// `AddBreadcrumb` which will modify the currently top-most scope.
// 2. the topmost scope can also be configured through the `ConfigureScope`
// method.
//
// Note that the scope can only be modified but not inspected.
// Only the client can use the scope to extract information currently.
// The scope is meant to be modified but not inspected directly. When preparing
// an event for reporting, the current client adds information from the current
// scope into the event.
type Scope struct {
mu sync.RWMutex
breadcrumbs []*Breadcrumb
@@ -47,6 +46,7 @@ type Scope struct {
eventProcessors []EventProcessor
}
// NewScope creates a new Scope.
func NewScope() *Scope {
scope := Scope{
breadcrumbs: make([]*Breadcrumb, 0),
@@ -309,6 +309,7 @@ func (scope *Scope) Clone() *Scope {
clone.level = scope.level
clone.transaction = scope.transaction
clone.request = scope.request
clone.requestBody = scope.requestBody
return clone
}

28
vendor/github.com/getsentry/sentry-go/sentry.go сгенерированный поставляемый
Просмотреть файл

@@ -5,14 +5,15 @@ import (
"time"
)
// Version is the version of the sentry-go SDK.
const Version = "0.6.1"
// Version is the version of the SDK.
const Version = "0.7.0"
// apiVersion is the minimum version of the Sentry API compatible with the
// sentry-go SDK.
const apiVersion = "7"
// Init initializes whole SDK by creating new `Client` and binding it to the current `Hub`
// Init initializes the SDK with options. The returned error is non-nil if
// options is invalid, for instance if a malformed DSN is provided.
func Init(options ClientOptions) error {
hub := CurrentHub()
client, err := NewClient(options)
@@ -47,7 +48,7 @@ func CaptureException(exception error) *EventID {
// CaptureEvent captures an event on the currently active client if any.
//
// The event must already be assembled. Typically code would instead use
// the utility methods like `CaptureException`. The return value is the
// the utility methods like CaptureException. The return value is the
// event ID. In case Sentry is disabled or event was dropped, the return value will be nil.
func CaptureEvent(event *Event) *EventID {
hub := CurrentHub()
@@ -63,7 +64,7 @@ func Recover() *EventID {
return nil
}
// Recover captures a panic and passes relevant context object.
// RecoverWithContext captures a panic and passes relevant context object.
func RecoverWithContext(ctx context.Context) *EventID {
if err := recover(); err != nil {
var hub *Hub
@@ -79,34 +80,25 @@ func RecoverWithContext(ctx context.Context) *EventID {
return nil
}
// WithScope temporarily pushes a scope for a single call.
//
// This function takes one argument, a callback that executes
// in the context of that scope.
//
// This is useful when extra data should be send with a single capture call
// for instance a different level or tags
// WithScope is a shorthand for CurrentHub().WithScope.
func WithScope(f func(scope *Scope)) {
hub := CurrentHub()
hub.WithScope(f)
}
// ConfigureScope invokes a function that can modify the current scope.
//
// The function is passed a mutable reference to the `Scope` so that modifications
// can be performed.
// ConfigureScope is a shorthand for CurrentHub().ConfigureScope.
func ConfigureScope(f func(scope *Scope)) {
hub := CurrentHub()
hub.ConfigureScope(f)
}
// PushScope pushes a new scope.
// PushScope is a shorthand for CurrentHub().PushPushScope.
func PushScope() {
hub := CurrentHub()
hub.PushScope()
}
// PopScope pushes a new scope.
// PopScope is a shorthand for CurrentHub().PopScope.
func PopScope() {
hub := CurrentHub()
hub.PopScope()

3
vendor/github.com/getsentry/sentry-go/sourcereader.go сгенерированный поставляемый
Просмотреть файл

@@ -36,11 +36,12 @@ func (sr *sourceReader) readContextLines(filename string, line, context int) ([]
return sr.calculateContextLines(lines, line, context)
}
// `contextLine` points to a line that caused an issue itself, in relation to returned slice
func (sr *sourceReader) calculateContextLines(lines [][]byte, line, context int) ([][]byte, int) {
// Stacktrace lines are 1-indexed, slices are 0-indexed
line--
// contextLine points to a line that caused an issue itself, in relation to
// returned slice.
contextLine := context
if lines == nil || line >= len(lines) || line < 0 {

91
vendor/github.com/getsentry/sentry-go/stacktrace.go сгенерированный поставляемый
Просмотреть файл

@@ -23,7 +23,7 @@ type Stacktrace struct {
FramesOmitted []uint `json:"frames_omitted,omitempty"`
}
// NewStacktrace creates a stacktrace using `runtime.Callers`.
// NewStacktrace creates a stacktrace using runtime.Callers.
func NewStacktrace() *Stacktrace {
pcs := make([]uintptr, 100)
n := runtime.Callers(1, pcs)
@@ -42,17 +42,21 @@ func NewStacktrace() *Stacktrace {
return &stacktrace
}
// ExtractStacktrace creates a new `Stacktrace` based on the given `error` object.
// TODO: Make it configurable so that anyone can provide their own implementation?
// Use of reflection allows us to not have a hard dependency on any given package, so we don't have to import it
// Use of reflection allows us to not have a hard dependency on any given
// package, so we don't have to import it.
// ExtractStacktrace creates a new Stacktrace based on the given error.
func ExtractStacktrace(err error) *Stacktrace {
method := extractReflectedStacktraceMethod(err)
if !method.IsValid() {
return nil
}
var pcs []uintptr
pcs := extractPcs(method)
if method.IsValid() {
pcs = extractPcs(method)
} else {
pcs = extractXErrorsPC(err)
}
if len(pcs) == 0 {
return nil
@@ -127,7 +131,34 @@ func extractPcs(method reflect.Value) []uintptr {
return pcs
}
// https://docs.sentry.io/development/sdk-dev/event-payloads/stacktrace/
// extractXErrorsPC extracts program counters from error values compatible with
// the error types from golang.org/x/xerrors.
//
// It returns nil if err is not compatible with errors from that package or if
// no program counters are stored in err.
func extractXErrorsPC(err error) []uintptr {
// This implementation uses the reflect package to avoid a hard dependency
// on third-party packages.
// We don't know if err matches the expected type. For simplicity, instead
// of trying to account for all possible ways things can go wrong, some
// assumptions are made and if they are violated the code will panic. We
// recover from any panic and ignore it, returning nil.
//nolint: errcheck
defer func() { recover() }()
field := reflect.ValueOf(err).Elem().FieldByName("frame") // type Frame struct{ frames [3]uintptr }
field = field.FieldByName("frames")
field = field.Slice(1, field.Len()) // drop first pc pointing to xerrors.New
pc := make([]uintptr, field.Len())
for i := 0; i < field.Len(); i++ {
pc[i] = uintptr(field.Index(i).Uint())
}
return pc
}
// Frame represents a function call and it's metadata. Frames are associated
// with a Stacktrace.
type Frame struct {
Function string `json:"function,omitempty"`
Symbol string `json:"symbol,omitempty"`
@@ -144,30 +175,46 @@ type Frame struct {
Vars map[string]interface{} `json:"vars,omitempty"`
}
// NewFrame assembles a stacktrace frame out of `runtime.Frame`.
// NewFrame assembles a stacktrace frame out of runtime.Frame.
func NewFrame(f runtime.Frame) Frame {
abspath := f.File
filename := f.File
var abspath, relpath string
// NOTE: f.File paths historically use forward slash as path separator even
// on Windows, though this is not yet documented, see
// https://golang.org/issues/3335. In any case, filepath.IsAbs can work with
// paths with either slash or backslash on Windows.
switch {
case f.File == "":
relpath = unknown
// Leave abspath as the empty string to be omitted when serializing
// event as JSON.
abspath = ""
case filepath.IsAbs(f.File):
abspath = f.File
// TODO: in the general case, it is not trivial to come up with a
// "project relative" path with the data we have in run time.
// We shall not use filepath.Base because it creates ambiguous paths and
// affects the "Suspect Commits" feature.
// For now, leave relpath empty to be omitted when serializing the event
// as JSON. Improve this later.
relpath = ""
default:
// f.File is a relative path. This may happen when the binary is built
// with the -trimpath flag.
relpath = f.File
// Omit abspath when serializing the event as JSON.
abspath = ""
}
function := f.Function
var pkg string
if filename != "" {
filename = filepath.Base(filename)
} else {
filename = unknown
}
if abspath == "" {
abspath = unknown
}
if function != "" {
pkg, function = splitQualifiedFunctionName(function)
}
frame := Frame{
AbsPath: abspath,
Filename: filename,
Filename: relpath,
Lineno: f.Line,
Module: pkg,
Function: function,

82
vendor/github.com/getsentry/sentry-go/transport.go сгенерированный поставляемый
Просмотреть файл

@@ -4,6 +4,8 @@ import (
"bytes"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
@@ -15,7 +17,7 @@ const defaultBufferSize = 30
const defaultRetryAfter = time.Second * 60
const defaultTimeout = time.Second * 30
// Transport is used by the `Client` to deliver events to remote server.
// Transport is used by the Client to deliver events to remote server.
type Transport interface {
Flush(timeout time.Duration) bool
Configure(options ClientOptions)
@@ -70,8 +72,10 @@ func getRequestBodyFromEvent(event *Event) []byte {
return body
}
partialMarshallMessage := "Original event couldn't be marshalled. Succeeded by stripping the data " +
"that uses interface{} type. Please verify that the data you attach to the scope is serializable."
partialMarshallMessage := fmt.Sprintf("Could not encode original event as JSON. "+
"Succeeded by removing Breadcrumbs, Contexts and Extra. "+
"Please verify the data you attach to the scope. "+
"Error: %s", err)
// Try to serialize the event, with all the contextual data that allows for interface{} stripped.
event.Breadcrumbs = nil
event.Contexts = nil
@@ -92,6 +96,40 @@ func getRequestBodyFromEvent(event *Event) []byte {
return nil
}
func getEnvelopeFromBody(body []byte, now time.Time) *bytes.Buffer {
var b bytes.Buffer
fmt.Fprintf(&b, `{"sent_at":"%s"}`, now.UTC().Format(time.RFC3339Nano))
fmt.Fprint(&b, "\n", `{"type":"transaction"}`, "\n")
b.Write(body)
return &b
}
func getRequestFromEvent(event *Event, dsn *Dsn) (*http.Request, error) {
body := getRequestBodyFromEvent(event)
if body == nil {
return nil, errors.New("event could not be marshalled")
}
if event.Type == transactionType {
env := getEnvelopeFromBody(body, time.Now())
request, _ := http.NewRequest(
http.MethodPost,
dsn.EnvelopeAPIURL().String(),
env,
)
return request, nil
}
request, _ := http.NewRequest(
http.MethodPost,
dsn.StoreAPIURL().String(),
bytes.NewBuffer(body),
)
return request, nil
}
// ================================
// HTTPTransport
// ================================
@@ -103,7 +141,7 @@ type batch struct {
done chan struct{} // closed to signal completion of all items
}
// HTTPTransport is a default implementation of `Transport` interface used by `Client`.
// HTTPTransport is a default implementation of Transport interface used by Client.
type HTTPTransport struct {
dsn *Dsn
client *http.Client
@@ -124,7 +162,7 @@ type HTTPTransport struct {
disabledUntil time.Time
}
// NewHTTPTransport returns a new pre-configured instance of HTTPTransport
// NewHTTPTransport returns a new pre-configured instance of HTTPTransport.
func NewHTTPTransport() *HTTPTransport {
transport := HTTPTransport{
BufferSize: defaultBufferSize,
@@ -133,7 +171,7 @@ func NewHTTPTransport() *HTTPTransport {
return &transport
}
// Configure is called by the `Client` itself, providing it it's own `ClientOptions`.
// Configure is called by the Client itself, providing it it's own ClientOptions.
func (t *HTTPTransport) Configure(options ClientOptions) {
dsn, err := NewDsn(options.Dsn)
if err != nil {
@@ -175,7 +213,7 @@ func (t *HTTPTransport) Configure(options ClientOptions) {
})
}
// SendEvent assembles a new packet out of `Event` and sends it to remote server.
// SendEvent assembles a new packet out of Event and sends it to remote server.
func (t *HTTPTransport) SendEvent(event *Event) {
if t.dsn == nil {
return
@@ -187,17 +225,11 @@ func (t *HTTPTransport) SendEvent(event *Event) {
return
}
body := getRequestBodyFromEvent(event)
if body == nil {
request, err := getRequestFromEvent(event, t.dsn)
if err != nil {
return
}
request, _ := http.NewRequest(
http.MethodPost,
t.dsn.StoreAPIURL().String(),
bytes.NewBuffer(body),
)
for headerKey, headerValue := range t.dsn.RequestHeaders() {
request.Header.Set(headerKey, headerValue)
}
@@ -332,7 +364,7 @@ func (t *HTTPTransport) worker() {
// HTTPSyncTransport
// ================================
// HTTPSyncTransport is an implementation of `Transport` interface which blocks after each captured event.
// HTTPSyncTransport is an implementation of Transport interface which blocks after each captured event.
type HTTPSyncTransport struct {
dsn *Dsn
client *http.Client
@@ -343,7 +375,7 @@ type HTTPSyncTransport struct {
Timeout time.Duration
}
// NewHTTPSyncTransport returns a new pre-configured instance of HTTPSyncTransport
// NewHTTPSyncTransport returns a new pre-configured instance of HTTPSyncTransport.
func NewHTTPSyncTransport() *HTTPSyncTransport {
transport := HTTPSyncTransport{
Timeout: defaultTimeout,
@@ -352,7 +384,7 @@ func NewHTTPSyncTransport() *HTTPSyncTransport {
return &transport
}
// Configure is called by the `Client` itself, providing it it's own `ClientOptions`.
// Configure is called by the Client itself, providing it it's own ClientOptions.
func (t *HTTPSyncTransport) Configure(options ClientOptions) {
dsn, err := NewDsn(options.Dsn)
if err != nil {
@@ -380,23 +412,17 @@ func (t *HTTPSyncTransport) Configure(options ClientOptions) {
}
}
// SendEvent assembles a new packet out of `Event` and sends it to remote server.
// SendEvent assembles a new packet out of Event and sends it to remote server.
func (t *HTTPSyncTransport) SendEvent(event *Event) {
if t.dsn == nil || time.Now().Before(t.disabledUntil) {
return
}
body := getRequestBodyFromEvent(event)
if body == nil {
request, err := getRequestFromEvent(event, t.dsn)
if err != nil {
return
}
request, _ := http.NewRequest(
http.MethodPost,
t.dsn.StoreAPIURL().String(),
bytes.NewBuffer(body),
)
for headerKey, headerValue := range t.dsn.RequestHeaders() {
request.Header.Set(headerKey, headerValue)
}
@@ -430,7 +456,7 @@ func (t *HTTPSyncTransport) Flush(_ time.Duration) bool {
// noopTransport
// ================================
// noopTransport is an implementation of `Transport` interface which drops all the events.
// noopTransport is an implementation of Transport interface which drops all the events.
// Only used internally when an empty DSN is provided, which effectively disables the SDK.
type noopTransport struct{}