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

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
}
}