https://mattermost.atlassian.net/browse/MM-34932

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2021-06-03 12:59:05 +05:30
коммит произвёл GitHub
родитель fff09bf210
Коммит 3299a72adb
776 изменённых файлов: 40081 добавлений и 44702 удалений

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

@@ -0,0 +1,5 @@
# Tell Git to use LF for line endings on all platforms.
# Required to have correct test data on Windows.
# https://github.com/mvdan/github-actions-golang#caveats
# https://github.com/actions/checkout/issues/135#issuecomment-613361104
* text eol=lf

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

@@ -20,7 +20,6 @@ linters:
- govet
- ineffassign
- interfacer
- lll
- maligned
- misspell
- nakedret

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

@@ -1,5 +1,19 @@
# Changelog
## v0.11.0
- feat(transports): Category-based Rate Limiting ([#354](https://github.com/getsentry/sentry-go/pull/354))
- feat(transports): Report User-Agent identifying SDK ([#357](https://github.com/getsentry/sentry-go/pull/357))
- fix(scope): Include event processors in clone ([#349](https://github.com/getsentry/sentry-go/pull/349))
- Improvements to `go doc` documentation ([#344](https://github.com/getsentry/sentry-go/pull/344), [#350](https://github.com/getsentry/sentry-go/pull/350), [#351](https://github.com/getsentry/sentry-go/pull/351))
- Miscellaneous changes to our testing infrastructure with GitHub Actions
([57123a40](https://github.com/getsentry/sentry-go/commit/57123a409be55f61b1d5a6da93c176c55a399ad0), [#128](https://github.com/getsentry/sentry-go/pull/128), [#338](https://github.com/getsentry/sentry-go/pull/338), [#345](https://github.com/getsentry/sentry-go/pull/345), [#346](https://github.com/getsentry/sentry-go/pull/346), [#352](https://github.com/getsentry/sentry-go/pull/352), [#353](https://github.com/getsentry/sentry-go/pull/353), [#355](https://github.com/getsentry/sentry-go/pull/355))
_NOTE:_
This version drops support for Go 1.13. The currently supported Go versions are the last 3 stable releases: 1.14, 1.15 and 1.16.
Users of the tracing functionality (`StartSpan`, etc) should upgrade to this version to benefit from separate rate limits for errors and transactions.
There are no breaking changes and upgrading should be a smooth experience for all users.
## v0.10.0
- feat: Debug connection reuse (#323)

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

@@ -129,7 +129,9 @@ type ClientOptions struct {
// and if applicable, caught errors type and value.
// If the match is found, then a whole event will be dropped.
IgnoreErrors []string
// Before send callback.
// BeforeSend is called before error events are sent to Sentry.
// Use it to mutate the event or return nil to discard the event.
// See EventProcessor if you need to mutate transactions.
BeforeSend func(event *Event, hint *EventHint) *Event
// Before breadcrumb add callback.
BeforeBreadcrumb func(breadcrumb *Breadcrumb, hint *BreadcrumbHint) *Breadcrumb

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

@@ -100,7 +100,7 @@ func NewDsn(rawURL string) (*Dsn, error) {
}
// ProjectID
if len(parsedURL.Path) == 0 || parsedURL.Path == "/" {
if parsedURL.Path == "" || parsedURL.Path == "/" {
return nil, &DsnParseError{"empty project id"}
}
pathSegments := strings.Split(parsedURL.Path[1:], "/")

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

@@ -1,6 +1,6 @@
module github.com/getsentry/sentry-go
go 1.13
go 1.14
require (
github.com/ajg/form v1.5.1 // indirect
@@ -9,7 +9,7 @@ require (
github.com/gin-gonic/gin v1.4.0
github.com/go-errors/errors v1.0.1
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab
github.com/google/go-cmp v0.4.0
github.com/google/go-cmp v0.5.5
github.com/google/go-querystring v1.0.0 // indirect
github.com/imkira/go-interpol v1.1.0 // indirect
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect

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

@@ -56,8 +56,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -81,7 +81,6 @@ github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yi
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
github.com/iris-contrib/schema v0.0.1 h1:10g/WnoRR+U+XXHWKBHeNy/+tZmM2kcAVGLOsz+yaDA=
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -175,7 +174,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
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 v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
@@ -205,7 +203,6 @@ github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcm
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876 h1:sKJQZMuxjOAR/Uo2LBfU90onWEf1dF4C+0hPJCc9Mpc=
golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -216,7 +213,6 @@ golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -230,7 +226,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -251,11 +246,9 @@ gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2G
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho=
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

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

@@ -170,8 +170,7 @@ func getIgnoreErrorsSuspects(event *Event) []string {
}
for _, ex := range event.Exception {
suspects = append(suspects, ex.Type)
suspects = append(suspects, ex.Value)
suspects = append(suspects, ex.Type, ex.Value)
}
return suspects

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

@@ -0,0 +1,41 @@
package ratelimit
import "strings"
// Reference:
// https://github.com/getsentry/relay/blob/0424a2e017d193a93918053c90cdae9472d164bf/relay-common/src/constants.rs#L116-L127
// Category classifies supported payload types that can be ingested by Sentry
// and, therefore, rate limited.
type Category string
// Known rate limit categories. As a special case, the CategoryAll applies to
// all known payload types.
const (
CategoryAll Category = ""
CategoryError Category = "error"
CategoryTransaction Category = "transaction"
)
// knownCategories is the set of currently known categories. Other categories
// are ignored for the purpose of rate-limiting.
var knownCategories = map[Category]struct{}{
CategoryAll: {},
CategoryError: {},
CategoryTransaction: {},
}
// String returns the category formatted for debugging.
func (c Category) String() string {
switch c {
case "":
return "CategoryAll"
default:
var b strings.Builder
b.WriteString("Category")
for _, w := range strings.Fields(string(c)) {
b.WriteString(strings.Title(w))
}
return b.String()
}
}

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

@@ -0,0 +1,22 @@
package ratelimit
import "time"
// A Deadline is a time instant when a rate limit expires.
type Deadline time.Time
// After reports whether the deadline d is after other.
func (d Deadline) After(other Deadline) bool {
return time.Time(d).After(time.Time(other))
}
// Equal reports whether d and e represent the same deadline.
func (d Deadline) Equal(e Deadline) bool {
return time.Time(d).Equal(time.Time(e))
}
// String returns the deadline formatted for debugging.
func (d Deadline) String() string {
// Like time.Time.String, but without the monotonic clock reading.
return time.Time(d).Round(0).String()
}

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

@@ -0,0 +1,3 @@
// Package ratelimit provides tools to work with rate limits imposed by Sentry's
// data ingestion pipeline.
package ratelimit

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

@@ -0,0 +1,64 @@
package ratelimit
import (
"net/http"
"time"
)
// Map maps categories to rate limit deadlines.
//
// A rate limit is in effect for a given category if either the category's
// deadline or the deadline for the special CategoryAll has not yet expired.
//
// Use IsRateLimited to check whether a category is rate-limited.
type Map map[Category]Deadline
// IsRateLimited returns true if the category is currently rate limited.
func (m Map) IsRateLimited(c Category) bool {
return m.isRateLimited(c, time.Now())
}
func (m Map) isRateLimited(c Category, now time.Time) bool {
return m.Deadline(c).After(Deadline(now))
}
// Deadline returns the deadline when the rate limit for the given category or
// the special CategoryAll expire, whichever is furthest into the future.
func (m Map) Deadline(c Category) Deadline {
categoryDeadline := m[c]
allDeadline := m[CategoryAll]
if categoryDeadline.After(allDeadline) {
return categoryDeadline
}
return allDeadline
}
// Merge merges the other map into m.
//
// If a category appears in both maps, the deadline that is furthest into the
// future is preserved.
func (m Map) Merge(other Map) {
for c, d := range other {
if d.After(m[c]) {
m[c] = d
}
}
}
// FromResponse returns a rate limit map from an HTTP response.
func FromResponse(r *http.Response) Map {
return fromResponse(r, time.Now())
}
func fromResponse(r *http.Response, now time.Time) Map {
s := r.Header.Get("X-Sentry-Rate-Limits")
if s != "" {
return parseXSentryRateLimits(s, now)
}
if r.StatusCode == http.StatusTooManyRequests {
s := r.Header.Get("Retry-After")
deadline, _ := parseRetryAfter(s, now)
return Map{CategoryAll: deadline}
}
return Map{}
}

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

@@ -0,0 +1,76 @@
package ratelimit
import (
"errors"
"math"
"strconv"
"strings"
"time"
)
var errInvalidXSRLRetryAfter = errors.New("invalid retry-after value")
// parseXSentryRateLimits returns a RateLimits map by parsing an input string in
// the format of the X-Sentry-Rate-Limits header.
//
// Example
//
// X-Sentry-Rate-Limits: 60:transaction, 2700:default;error;security
//
// This will rate limit transactions for the next 60 seconds and errors for the
// next 2700 seconds.
//
// Limits for unknown categories are ignored.
func parseXSentryRateLimits(s string, now time.Time) Map {
// https://github.com/getsentry/relay/blob/0424a2e017d193a93918053c90cdae9472d164bf/relay-server/src/utils/rate_limits.rs#L44-L82
m := make(Map, len(knownCategories))
for _, limit := range strings.Split(s, ",") {
limit = strings.TrimSpace(limit)
if limit == "" {
continue
}
components := strings.Split(limit, ":")
if len(components) == 0 {
continue
}
retryAfter, err := parseXSRLRetryAfter(strings.TrimSpace(components[0]), now)
if err != nil {
continue
}
categories := ""
if len(components) > 1 {
categories = components[1]
}
for _, category := range strings.Split(categories, ";") {
c := Category(strings.ToLower(strings.TrimSpace(category)))
if _, ok := knownCategories[c]; !ok {
// skip unknown categories, keep m small
continue
}
// always keep the deadline furthest into the future
if retryAfter.After(m[c]) {
m[c] = retryAfter
}
}
}
return m
}
// parseXSRLRetryAfter parses a string into a retry-after rate limit deadline.
//
// Valid input is a number, possibly signed and possibly floating-point,
// indicating the number of seconds to wait before sending another request.
// Negative values are treated as zero. Fractional values are rounded to the
// next integer.
func parseXSRLRetryAfter(s string, now time.Time) (Deadline, error) {
// https://github.com/getsentry/relay/blob/0424a2e017d193a93918053c90cdae9472d164bf/relay-quotas/src/rate_limit.rs#L88-L96
f, err := strconv.ParseFloat(s, 64)
if err != nil {
return Deadline{}, errInvalidXSRLRetryAfter
}
d := time.Duration(math.Ceil(math.Max(f, 0.0))) * time.Second
if d < 0 {
d = 0
}
return Deadline(now.Add(d)), nil
}

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

@@ -0,0 +1,40 @@
package ratelimit
import (
"errors"
"strconv"
"time"
)
const defaultRetryAfter = 1 * time.Minute
var errInvalidRetryAfter = errors.New("invalid input")
// parseRetryAfter parses a string s as in the standard Retry-After HTTP header
// and returns a deadline until when requests are rate limited and therefore new
// requests should not be sent. The input may be either a date or a non-negative
// integer number of seconds.
//
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
//
// parseRetryAfter always returns a usable deadline, even in case of an error.
//
// This is the original rate limiting mechanism used by Sentry, superseeded by
// the X-Sentry-Rate-Limits response header.
func parseRetryAfter(s string, now time.Time) (Deadline, error) {
if s == "" {
goto invalid
}
if n, err := strconv.Atoi(s); err == nil {
if n < 0 {
goto invalid
}
d := time.Duration(n) * time.Second
return Deadline(now.Add(d)), nil
}
if date, err := time.Parse(time.RFC1123, s); err == nil {
return Deadline(date), nil
}
invalid:
return Deadline(now.Add(defaultRetryAfter)), errInvalidRetryAfter
}

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

@@ -318,7 +318,7 @@ func (scope *Scope) Clone() *Scope {
clone.transaction = scope.transaction
clone.request = scope.request
clone.requestBody = scope.requestBody
clone.eventProcessors = scope.eventProcessors
return clone
}

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

@@ -6,12 +6,15 @@ import (
)
// Version is the version of the SDK.
const Version = "0.10.0"
const Version = "0.11.0"
// apiVersion is the minimum version of the Sentry API compatible with the
// sentry-go SDK.
const apiVersion = "7"
// userAgent is the User-Agent of outgoing HTTP requests.
const userAgent = "sentry-go/" + Version
// 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 {

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

@@ -10,13 +10,13 @@ import (
"io/ioutil"
"net/http"
"net/url"
"strconv"
"sync"
"time"
"github.com/getsentry/sentry-go/internal/ratelimit"
)
const defaultBufferSize = 30
const defaultRetryAfter = time.Second * 60
const defaultTimeout = time.Second * 30
// maxDrainResponseBytes is the maximum number of bytes that transport
@@ -61,26 +61,6 @@ func getTLSConfig(options ClientOptions) *tls.Config {
return nil
}
func retryAfter(now time.Time, r *http.Response) time.Duration {
// TODO(tracing): handle x-sentry-rate-limits, separate rate limiting
// per data type (error event, transaction, etc).
retryAfterHeader := r.Header["Retry-After"]
if retryAfterHeader == nil {
return defaultRetryAfter
}
if date, err := time.Parse(time.RFC1123, retryAfterHeader[0]); err == nil {
return date.Sub(now)
}
if seconds, err := strconv.Atoi(retryAfterHeader[0]); err == nil {
return time.Second * time.Duration(seconds)
}
return defaultRetryAfter
}
func getRequestBodyFromEvent(event *Event) []byte {
body, err := json.Marshal(event)
if err == nil {
@@ -144,7 +124,12 @@ func transactionEnvelopeFromBody(eventID EventID, sentAt time.Time, body json.Ra
return &b, nil
}
func getRequestFromEvent(event *Event, dsn *Dsn) (*http.Request, error) {
func getRequestFromEvent(event *Event, dsn *Dsn) (r *http.Request, err error) {
defer func() {
if r != nil {
r.Header.Set("User-Agent", userAgent)
}
}()
body := getRequestBodyFromEvent(event)
if body == nil {
return nil, errors.New("event could not be marshaled")
@@ -167,18 +152,38 @@ func getRequestFromEvent(event *Event, dsn *Dsn) (*http.Request, error) {
)
}
func categoryFor(eventType string) ratelimit.Category {
switch eventType {
case "":
return ratelimit.CategoryError
case transactionType:
return ratelimit.CategoryTransaction
default:
return ratelimit.Category(eventType)
}
}
// ================================
// HTTPTransport
// ================================
// A batch groups items that are processed sequentially.
type batch struct {
items chan *http.Request
items chan batchItem
started chan struct{} // closed to signal items started to be worked on
done chan struct{} // closed to signal completion of all items
}
// HTTPTransport is a default implementation of Transport interface used by Client.
type batchItem struct {
request *http.Request
category ratelimit.Category
}
// HTTPTransport is the default, non-blocking, implementation of Transport.
//
// Clients using this transport will enqueue requests in a buffer and return to
// the caller before any network communication has happened. Requests are sent
// to Sentry sequentially from a background goroutine.
type HTTPTransport struct {
dsn *Dsn
client *http.Client
@@ -195,8 +200,8 @@ type HTTPTransport struct {
// HTTP Client request timeout. Defaults to 30 seconds.
Timeout time.Duration
mu sync.RWMutex
disabledUntil time.Time
mu sync.RWMutex
limits ratelimit.Map
}
// NewHTTPTransport returns a new pre-configured instance of HTTPTransport.
@@ -204,6 +209,7 @@ func NewHTTPTransport() *HTTPTransport {
transport := HTTPTransport{
BufferSize: defaultBufferSize,
Timeout: defaultTimeout,
limits: make(ratelimit.Map),
}
return &transport
}
@@ -222,7 +228,7 @@ func (t *HTTPTransport) Configure(options ClientOptions) {
// synchronized by reading from and writing to the channel.
t.buffer = make(chan batch, 1)
t.buffer <- batch{
items: make(chan *http.Request, t.BufferSize),
items: make(chan batchItem, t.BufferSize),
started: make(chan struct{}),
done: make(chan struct{}),
}
@@ -255,10 +261,10 @@ func (t *HTTPTransport) SendEvent(event *Event) {
if t.dsn == nil {
return
}
t.mu.RLock()
disabled := time.Now().Before(t.disabledUntil)
t.mu.RUnlock()
if disabled {
category := categoryFor(event.Type)
if t.disabled(category) {
return
}
@@ -285,7 +291,10 @@ func (t *HTTPTransport) SendEvent(event *Event) {
b := <-t.buffer
select {
case b.items <- request:
case b.items <- batchItem{
request: request,
category: category,
}:
var eventType string
if event.Type == transactionType {
eventType = "transaction"
@@ -346,7 +355,7 @@ started:
close(b.items)
// Start a new batch for subsequent events.
t.buffer <- batch{
items: make(chan *http.Request, t.BufferSize),
items: make(chan batchItem, t.BufferSize),
started: make(chan struct{}),
done: make(chan struct{}),
}
@@ -375,26 +384,19 @@ func (t *HTTPTransport) worker() {
t.buffer <- b
// Process all batch items.
for request := range b.items {
t.mu.RLock()
disabled := time.Now().Before(t.disabledUntil)
t.mu.RUnlock()
if disabled {
for item := range b.items {
if t.disabled(item.category) {
continue
}
response, err := t.client.Do(request)
response, err := t.client.Do(item.request)
if err != nil {
Logger.Printf("There was an issue with sending an event: %v", err)
continue
}
if response.StatusCode == http.StatusTooManyRequests {
deadline := time.Now().Add(retryAfter(time.Now(), response))
t.mu.Lock()
t.disabledUntil = deadline
t.mu.Unlock()
Logger.Printf("Too many requests, backing off till: %s\n", deadline)
}
t.mu.Lock()
t.limits.Merge(ratelimit.FromResponse(response))
t.mu.Unlock()
// Drain body up to a limit and close it, allowing the
// transport to reuse TCP connections.
_, _ = io.CopyN(ioutil.Discard, response.Body, maxDrainResponseBytes)
@@ -406,16 +408,38 @@ func (t *HTTPTransport) worker() {
}
}
func (t *HTTPTransport) disabled(c ratelimit.Category) bool {
t.mu.RLock()
defer t.mu.RUnlock()
disabled := t.limits.IsRateLimited(c)
if disabled {
Logger.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c))
}
return disabled
}
// ================================
// HTTPSyncTransport
// ================================
// HTTPSyncTransport is an implementation of Transport interface which blocks after each captured event.
// HTTPSyncTransport is a blocking implementation of Transport.
//
// Clients using this transport will send requests to Sentry sequentially and
// block until a response is returned.
//
// The blocking behavior is useful in a limited set of use cases. For example,
// use it when deploying code to a Function as a Service ("Serverless")
// platform, where any work happening in a background goroutine is not
// guaranteed to execute.
//
// For most cases, prefer HTTPTransport.
type HTTPSyncTransport struct {
dsn *Dsn
client *http.Client
transport http.RoundTripper
disabledUntil time.Time
dsn *Dsn
client *http.Client
transport http.RoundTripper
mu sync.Mutex
limits ratelimit.Map
// HTTP Client request timeout. Defaults to 30 seconds.
Timeout time.Duration
@@ -425,6 +449,7 @@ type HTTPSyncTransport struct {
func NewHTTPSyncTransport() *HTTPSyncTransport {
transport := HTTPSyncTransport{
Timeout: defaultTimeout,
limits: make(ratelimit.Map),
}
return &transport
@@ -460,7 +485,11 @@ func (t *HTTPSyncTransport) Configure(options ClientOptions) {
// 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) {
if t.dsn == nil {
return
}
if t.disabled(categoryFor(event.Type)) {
return
}
@@ -492,10 +521,10 @@ func (t *HTTPSyncTransport) SendEvent(event *Event) {
Logger.Printf("There was an issue with sending an event: %v", err)
return
}
if response.StatusCode == http.StatusTooManyRequests {
t.disabledUntil = time.Now().Add(retryAfter(time.Now(), response))
Logger.Printf("Too many requests, backing off till: %s\n", t.disabledUntil)
}
t.mu.Lock()
t.limits.Merge(ratelimit.FromResponse(response))
t.mu.Unlock()
// Drain body up to a limit and close it, allowing the
// transport to reuse TCP connections.
_, _ = io.CopyN(ioutil.Discard, response.Body, maxDrainResponseBytes)
@@ -507,6 +536,16 @@ func (t *HTTPSyncTransport) Flush(_ time.Duration) bool {
return true
}
func (t *HTTPSyncTransport) disabled(c ratelimit.Category) bool {
t.mu.Lock()
defer t.mu.Unlock()
disabled := t.limits.IsRateLimited(c)
if disabled {
Logger.Printf("Too many requests for %q, backing off till: %v", c, t.limits.Deadline(c))
}
return disabled
}
// ================================
// noopTransport
// ================================