Update deps
This commit is contained in:
36
vendor/github.com/briandowns/openweathermap/current.go
generated
vendored
36
vendor/github.com/briandowns/openweathermap/current.go
generated
vendored
@@ -25,24 +25,24 @@ import (
|
||||
// CurrentWeatherData struct contains an aggregate view of the structs
|
||||
// defined above for JSON to be unmarshaled into.
|
||||
type CurrentWeatherData struct {
|
||||
GeoPos Coordinates `json:"coord"`
|
||||
Sys Sys `json:"sys"`
|
||||
Base string `json:"base"`
|
||||
Weather []Weather `json:"weather"`
|
||||
Main Main `json:"main"`
|
||||
Visibility int `json:"visibility"`
|
||||
Wind Wind `json:"wind"`
|
||||
Clouds Clouds `json:"clouds"`
|
||||
Rain Rain `json:"rain"`
|
||||
Snow Snow `json:"snow"`
|
||||
Dt int `json:"dt"`
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Cod int `json:"cod"`
|
||||
Timezone int `json:"timezone"`
|
||||
Unit string
|
||||
Lang string
|
||||
Key string
|
||||
GeoPos Coordinates `json:"coord"`
|
||||
Sys Sys `json:"sys"`
|
||||
Base string `json:"base"`
|
||||
Weather []Weather `json:"weather"`
|
||||
Main Main `json:"main"`
|
||||
Visibility int `json:"visibility"`
|
||||
Wind Wind `json:"wind"`
|
||||
Clouds Clouds `json:"clouds"`
|
||||
Rain Rain `json:"rain"`
|
||||
Snow Snow `json:"snow"`
|
||||
Dt int `json:"dt"`
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Cod int `json:"cod"`
|
||||
Timezone int `json:"timezone"`
|
||||
Unit string
|
||||
Lang string
|
||||
Key string
|
||||
*Settings
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/briandowns/openweathermap/history.go
generated
vendored
2
vendor/github.com/briandowns/openweathermap/history.go
generated
vendored
@@ -68,7 +68,7 @@ type HistoricalWeatherData struct {
|
||||
}
|
||||
|
||||
// NewHistorical returns a new HistoricalWeatherData pointer with
|
||||
//the supplied arguments.
|
||||
// the supplied arguments.
|
||||
func NewHistorical(unit, key string, options ...Option) (*HistoricalWeatherData, error) {
|
||||
h := &HistoricalWeatherData{
|
||||
Settings: NewSettings(),
|
||||
|
||||
52
vendor/github.com/briandowns/openweathermap/onecall.go
generated
vendored
52
vendor/github.com/briandowns/openweathermap/onecall.go
generated
vendored
@@ -17,20 +17,22 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// OneCallData struct contains an aggregate view of the structs
|
||||
// defined above for JSON to be unmarshaled into.
|
||||
type OneCallData struct {
|
||||
Latitude float64 `json:"lat"`
|
||||
Longitude float64 `json:"lon"`
|
||||
Timezone string `json:"timezone"`
|
||||
TimezoneOffset int `json:"timezone_offset"`
|
||||
Current OneCallCurrentData `json:"current,omitempty"`
|
||||
Minutely []OneCallMinutelyData `json:"minutely,omitempty"`
|
||||
Hourly []OneCallHourlyData `json:"hourly,omitempty"`
|
||||
Daily []OneCallDailyData `json:"daily,omitempty"`
|
||||
Alerts []OneCallAlertData `json:"alerts,omitempty"`
|
||||
Latitude float64 `json:"lat"`
|
||||
Longitude float64 `json:"lon"`
|
||||
Timezone string `json:"timezone"`
|
||||
TimezoneOffset int `json:"timezone_offset"`
|
||||
Current OneCallCurrentData `json:"current,omitempty"`
|
||||
Minutely []OneCallMinutelyData `json:"minutely,omitempty"`
|
||||
Hourly []OneCallHourlyData `json:"hourly,omitempty"`
|
||||
Daily []OneCallDailyData `json:"daily,omitempty"`
|
||||
Alerts []OneCallAlertData `json:"alerts,omitempty"`
|
||||
Data []OneCallTimeMachineData `json:"data,omitempty"`
|
||||
|
||||
Unit string
|
||||
Lang string
|
||||
@@ -39,6 +41,24 @@ type OneCallData struct {
|
||||
*Settings
|
||||
}
|
||||
|
||||
type OneCallTimeMachineData struct {
|
||||
Dt int `json:"dt"`
|
||||
Sunrise int `json:"sunrise"`
|
||||
Sunset int `json:"sunset"`
|
||||
Temp float64 `json:"temp"`
|
||||
FeelsLike float64 `json:"feels_like"`
|
||||
Pressure int `json:"pressure"`
|
||||
Humidity int `json:"humidity"`
|
||||
DewPoint float64 `json:"dew_point"`
|
||||
Clouds int `json:"clouds"`
|
||||
UVI float64 `json:"uvi"`
|
||||
Visibility int `json:"visibility"`
|
||||
WindSpeed float64 `json:"wind_speed"`
|
||||
WindGust float64 `json:"wind_gust,omitempty"`
|
||||
WindDeg float64 `json:"wind_deg"`
|
||||
Weather []Weather `json:"weather"`
|
||||
}
|
||||
|
||||
type OneCallCurrentData struct {
|
||||
Dt int `json:"dt"`
|
||||
Sunrise int `json:"sunrise"`
|
||||
@@ -161,7 +181,19 @@ func NewOneCall(unit, lang, key string, excludes []string, options ...Option) (*
|
||||
// OneCallByCoordinates will provide the onecall weather with the
|
||||
// provided location coordinates.
|
||||
func (w *OneCallData) OneCallByCoordinates(location *Coordinates) error {
|
||||
response, err := w.client.Get(fmt.Sprintf(fmt.Sprintf(onecallURL, "appid=%s&lat=%f&lon=%f&units=%s&lang=%s&exclude=%s"), w.Key, location.Latitude, location.Longitude, w.Unit, w.Lang, w.Excludes))
|
||||
response, err := w.client.Get(fmt.Sprintf(fmt.Sprintf(onecallURL, "?appid=%s&lat=%f&lon=%f&units=%s&lang=%s&exclude=%s"), w.Key, location.Latitude, location.Longitude, w.Unit, w.Lang, w.Excludes))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
return json.NewDecoder(response.Body).Decode(&w)
|
||||
}
|
||||
|
||||
// OneCallTimeMachine will provide the onecall timemachine weather with the
|
||||
// provided location coordinates and unix timestamp
|
||||
func (w *OneCallData) OneCallTimeMachine(location *Coordinates, datetime time.Time) error {
|
||||
response, err := w.client.Get(fmt.Sprintf(fmt.Sprintf(onecallURL, "/timemachine?appid=%s&lat=%f&lon=%f&units=%s&lang=%s&dt=%d"), w.Key, location.Latitude, location.Longitude, w.Unit, w.Lang, datetime.Unix()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
2
vendor/github.com/briandowns/openweathermap/openweathermap.go
generated
vendored
2
vendor/github.com/briandowns/openweathermap/openweathermap.go
generated
vendored
@@ -35,7 +35,7 @@ var (
|
||||
var DataUnits = map[string]string{"C": "metric", "F": "imperial", "K": "internal"}
|
||||
var (
|
||||
baseURL = "https://api.openweathermap.org/data/2.5/weather?%s"
|
||||
onecallURL = "https://api.openweathermap.org/data/3.0/onecall?%s"
|
||||
onecallURL = "https://api.openweathermap.org/data/3.0/onecall%s"
|
||||
iconURL = "https://openweathermap.org/img/w/%s"
|
||||
groupURL = "http://api.openweathermap.org/data/2.5/group?%s"
|
||||
stationURL = "https://api.openweathermap.org/data/2.5/station?id=%d"
|
||||
|
||||
30
vendor/github.com/briandowns/openweathermap/uv.go
generated
vendored
30
vendor/github.com/briandowns/openweathermap/uv.go
generated
vendored
@@ -106,33 +106,33 @@ type UVIndexInfo struct {
|
||||
// UVData contains data in regards to UV index ranges, rankings, and steps for protection
|
||||
var UVData = []UVIndexInfo{
|
||||
{
|
||||
UVIndex: []float64{0, 2.9},
|
||||
MGC: "Green",
|
||||
Risk: "Low",
|
||||
UVIndex: []float64{0, 2.9},
|
||||
MGC: "Green",
|
||||
Risk: "Low",
|
||||
RecommendedProtection: "Wear sunglasses on bright days; use sunscreen if there is snow on the ground, which reflects UV radiation, or if you have particularly fair skin.",
|
||||
},
|
||||
{
|
||||
UVIndex: []float64{3, 5.9},
|
||||
MGC: "Yellow",
|
||||
Risk: "Moderate",
|
||||
UVIndex: []float64{3, 5.9},
|
||||
MGC: "Yellow",
|
||||
Risk: "Moderate",
|
||||
RecommendedProtection: "Take precautions, such as covering up, if you will be outside. Stay in shade near midday when the sun is strongest.",
|
||||
},
|
||||
{
|
||||
UVIndex: []float64{6, 7.9},
|
||||
MGC: "Orange",
|
||||
Risk: "High",
|
||||
UVIndex: []float64{6, 7.9},
|
||||
MGC: "Orange",
|
||||
Risk: "High",
|
||||
RecommendedProtection: "Cover the body with sun protective clothing, use SPF 30+ sunscreen, wear a hat, reduce time in the sun within three hours of solar noon, and wear sunglasses.",
|
||||
},
|
||||
{
|
||||
UVIndex: []float64{8, 10.9},
|
||||
MGC: "Red",
|
||||
Risk: "Very high",
|
||||
UVIndex: []float64{8, 10.9},
|
||||
MGC: "Red",
|
||||
Risk: "Very high",
|
||||
RecommendedProtection: "Wear SPF 30+ sunscreen, a shirt, sunglasses, and a wide-brimmed hat. Do not stay in the sun for too long.",
|
||||
},
|
||||
{
|
||||
UVIndex: []float64{11},
|
||||
MGC: "Violet",
|
||||
Risk: "Extreme",
|
||||
UVIndex: []float64{11},
|
||||
MGC: "Violet",
|
||||
Risk: "Extreme",
|
||||
RecommendedProtection: "Take all precautions: Wear SPF 30+ sunscreen, a long-sleeved shirt and trousers, sunglasses, and a very broad hat. Avoid the sun within three hours of solar noon.",
|
||||
},
|
||||
}
|
||||
|
||||
32
vendor/github.com/carlmjohnson/requests/config.go
generated
vendored
32
vendor/github.com/carlmjohnson/requests/config.go
generated
vendored
@@ -2,7 +2,9 @@ package requests
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
@@ -43,3 +45,33 @@ func TestServerConfig(s *httptest.Server) Config {
|
||||
Client(s.Client())
|
||||
}
|
||||
}
|
||||
|
||||
// BodyMultipart returns a Config
|
||||
// that uses a multipart.Writer for the request body.
|
||||
// If boundary is "", a multipart boundary is chosen at random.
|
||||
// The content type of the request is set to multipart/form-data
|
||||
// with the correct boundary.
|
||||
// The multipart.Writer is automatically closed if the callback succeeds.
|
||||
func BodyMultipart(boundary string, h func(multi *multipart.Writer) error) Config {
|
||||
return func(rb *Builder) {
|
||||
if boundary == "" {
|
||||
multi := multipart.NewWriter(nil)
|
||||
boundary = multi.Boundary()
|
||||
}
|
||||
rb.
|
||||
ContentType("multipart/form-data; boundary=" + boundary).
|
||||
BodyWriter(func(w io.Writer) error {
|
||||
multi := multipart.NewWriter(w)
|
||||
if err := multi.SetBoundary(boundary); err != nil {
|
||||
return fmt.Errorf("setting boundary: %w", err)
|
||||
}
|
||||
if err := h(multi); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := multi.Close(); err != nil {
|
||||
return fmt.Errorf("closing multipart writer: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
40
vendor/github.com/cockroachdb/logtags/buffer.go
generated
vendored
40
vendor/github.com/cockroachdb/logtags/buffer.go
generated
vendored
@@ -26,13 +26,47 @@ type Buffer struct {
|
||||
}
|
||||
|
||||
// SingleTagBuffer returns a Buffer with a single tag.
|
||||
func SingleTagBuffer(key string, value interface{}) *Buffer {
|
||||
func SingleTagBuffer(key string, value any) *Buffer {
|
||||
b := &Buffer{}
|
||||
b.init(1, 1)
|
||||
b.tags[0] = Tag{key: key, value: value}
|
||||
return b
|
||||
}
|
||||
|
||||
// BuildBuffer is used to build a *Buffer that contains an arbitrary number
|
||||
// of tags. Sample usage:
|
||||
//
|
||||
// bld := BuildBuffer()
|
||||
// bld.Add("a", 1)
|
||||
// bld.Add("b", 2)
|
||||
// buf := bld.Finish()
|
||||
//
|
||||
// It is equivalent to using SingleTagBuffer() followed by Buffer.Add() calls,
|
||||
// but avoids allocating each intermediate buffer.
|
||||
func BuildBuffer() BufferBuilder {
|
||||
bld := BufferBuilder{b: &Buffer{}}
|
||||
bld.b.init(0, 0)
|
||||
return bld
|
||||
}
|
||||
|
||||
// BufferBuilder is returned by BuildBuffer.
|
||||
type BufferBuilder struct {
|
||||
b *Buffer
|
||||
}
|
||||
|
||||
// Add a log tag to the buffer. If the key was added already, the value is
|
||||
// replaced.
|
||||
func (bld *BufferBuilder) Add(key string, value any) {
|
||||
bld.b.addOrReplace(key, value)
|
||||
}
|
||||
|
||||
// Finish returns the buffer with the tags that were added to the builder.
|
||||
func (bld *BufferBuilder) Finish() *Buffer {
|
||||
b := bld.b
|
||||
bld.b = nil
|
||||
return b
|
||||
}
|
||||
|
||||
// Get returns the tags, as a slice. This slice must not be modified.
|
||||
func (b *Buffer) Get() []Tag {
|
||||
return b.tags
|
||||
@@ -55,7 +89,7 @@ func (b *Buffer) GetTag(key string) (Tag, bool) {
|
||||
// Add returns a new buffer with one more tag. If the tag has the same key as an
|
||||
// earlier tag, that tag is overwritten.
|
||||
// The receiver can be nil.
|
||||
func (b *Buffer) Add(key string, value interface{}) *Buffer {
|
||||
func (b *Buffer) Add(key string, value any) *Buffer {
|
||||
if b == nil {
|
||||
return SingleTagBuffer(key, value)
|
||||
}
|
||||
@@ -191,7 +225,7 @@ func (b *Buffer) init(length, capacityHint int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Buffer) addOrReplace(key string, value interface{}) {
|
||||
func (b *Buffer) addOrReplace(key string, value any) {
|
||||
for i := range b.tags {
|
||||
if b.tags[i].key == key {
|
||||
b.tags[i].value = value
|
||||
|
||||
22
vendor/github.com/cockroachdb/logtags/context.go
generated
vendored
22
vendor/github.com/cockroachdb/logtags/context.go
generated
vendored
@@ -21,6 +21,9 @@ type contextLogTagsKey struct{}
|
||||
// FromContext returns the tags stored in the context (by WithTags, AddTag, or
|
||||
// AddTags).
|
||||
func FromContext(ctx context.Context) *Buffer {
|
||||
if fromContextFn != nil {
|
||||
return fromContextFn(ctx)
|
||||
}
|
||||
val := ctx.Value(contextLogTagsKey{})
|
||||
if val == nil {
|
||||
return nil
|
||||
@@ -31,6 +34,9 @@ func FromContext(ctx context.Context) *Buffer {
|
||||
// WithTags returns a context with the given tags. Any existing tags are
|
||||
// ignored.
|
||||
func WithTags(ctx context.Context, tags *Buffer) context.Context {
|
||||
if withTagsFn != nil {
|
||||
return withTagsFn(ctx, tags)
|
||||
}
|
||||
return context.WithValue(ctx, contextLogTagsKey{}, tags)
|
||||
}
|
||||
|
||||
@@ -63,3 +69,19 @@ func AddTags(ctx context.Context, tags *Buffer) context.Context {
|
||||
}
|
||||
return WithTags(ctx, newB)
|
||||
}
|
||||
|
||||
// OverrideContextFuncs can be used to override the implementation of
|
||||
// FromContext and WithTags. This is useful if we have a more efficient
|
||||
// implementation of context-associated values.
|
||||
//
|
||||
// Must be called before WithTags or FromContext are called.
|
||||
func OverrideContextFuncs(
|
||||
fromContext func(ctx context.Context) *Buffer,
|
||||
withTags func(ctx context.Context, tags *Buffer) context.Context,
|
||||
) {
|
||||
fromContextFn = fromContext
|
||||
withTagsFn = withTags
|
||||
}
|
||||
|
||||
var fromContextFn func(ctx context.Context) *Buffer
|
||||
var withTagsFn func(ctx context.Context, tags *Buffer) context.Context
|
||||
|
||||
11
vendor/github.com/cockroachdb/pebble/checkpoint.go
generated
vendored
11
vendor/github.com/cockroachdb/pebble/checkpoint.go
generated
vendored
@@ -88,23 +88,20 @@ func mkdirAllAndSyncParents(fs vfs.FS, destDir string) (vfs.File, error) {
|
||||
// Collect paths for all directories between destDir (excluded) and its
|
||||
// closest existing ancestor (included).
|
||||
var parentPaths []string
|
||||
foundExistingAncestor := false
|
||||
for parentPath := fs.PathDir(destDir); parentPath != "."; parentPath = fs.PathDir(parentPath) {
|
||||
for parentPath := fs.PathDir(destDir); ; parentPath = fs.PathDir(parentPath) {
|
||||
parentPaths = append(parentPaths, parentPath)
|
||||
if fs.PathDir(parentPath) == parentPath {
|
||||
break
|
||||
}
|
||||
_, err := fs.Stat(parentPath)
|
||||
if err == nil {
|
||||
// Exit loop at the closest existing ancestor.
|
||||
foundExistingAncestor = true
|
||||
break
|
||||
}
|
||||
if !oserror.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Handle empty filesystem edge case.
|
||||
if !foundExistingAncestor {
|
||||
parentPaths = append(parentPaths, "")
|
||||
}
|
||||
// Create destDir and any of its missing parents.
|
||||
if err := fs.MkdirAll(destDir, 0755); err != nil {
|
||||
return nil, err
|
||||
|
||||
4
vendor/github.com/cockroachdb/pebble/internal/manual/manual_64bit.go
generated
vendored
4
vendor/github.com/cockroachdb/pebble/internal/manual/manual_64bit.go
generated
vendored
@@ -2,8 +2,8 @@
|
||||
// of this source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || s390x || sparc64 || riscv64
|
||||
// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le s390x sparc64 riscv64
|
||||
//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || s390x || sparc64 || riscv64 || loong64
|
||||
// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le s390x sparc64 riscv64 loong64
|
||||
|
||||
package manual
|
||||
|
||||
|
||||
4
vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_64bit.go
generated
vendored
4
vendor/github.com/cockroachdb/pebble/internal/rawalloc/rawalloc_64bit.go
generated
vendored
@@ -12,8 +12,8 @@
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || s390x || sparc64 || riscv64
|
||||
// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le s390x sparc64 riscv64
|
||||
//go:build amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || s390x || sparc64 || riscv64 || loong64
|
||||
// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le s390x sparc64 riscv64 loong64
|
||||
|
||||
package rawalloc
|
||||
|
||||
|
||||
3
vendor/github.com/cockroachdb/pebble/vfs/mem_fs.go
generated
vendored
3
vendor/github.com/cockroachdb/pebble/vfs/mem_fs.go
generated
vendored
@@ -164,6 +164,9 @@ func (y *MemFS) walk(fullname string, f func(dir *memNode, frag string, final bo
|
||||
for len(fullname) > 0 && fullname[0] == sep[0] {
|
||||
fullname = fullname[1:]
|
||||
}
|
||||
if fullname == "." {
|
||||
fullname = ""
|
||||
}
|
||||
dir := y.root
|
||||
|
||||
for {
|
||||
|
||||
10
vendor/github.com/cockroachdb/redact/builder/builder.go
generated
vendored
10
vendor/github.com/cockroachdb/redact/builder/builder.go
generated
vendored
@@ -130,6 +130,16 @@ func (b *StringBuilder) SafeRune(s i.SafeRune) {
|
||||
_ = b.Buffer.WriteRune(rune(s))
|
||||
}
|
||||
|
||||
func (b *StringBuilder) SafeByte(s i.SafeByte) {
|
||||
b.SetMode(ib.SafeEscaped)
|
||||
_ = b.Buffer.WriteByte(byte(s))
|
||||
}
|
||||
|
||||
func (b *StringBuilder) SafeBytes(s i.SafeBytes) {
|
||||
b.SetMode(ib.SafeEscaped)
|
||||
_, _ = b.Buffer.Write([]byte(s))
|
||||
}
|
||||
|
||||
// UnsafeString is part of the SafeWriter interface.
|
||||
func (b *StringBuilder) UnsafeString(s string) {
|
||||
b.SetMode(ib.UnsafeEscaped)
|
||||
|
||||
18
vendor/github.com/cockroachdb/redact/interfaces/interfaces.go
generated
vendored
18
vendor/github.com/cockroachdb/redact/interfaces/interfaces.go
generated
vendored
@@ -65,6 +65,12 @@ type SafeWriter interface {
|
||||
// SafeRune emits a safe rune.
|
||||
SafeRune(SafeRune)
|
||||
|
||||
// SafeByte emits a safe byte.
|
||||
SafeByte(SafeByte)
|
||||
|
||||
// SafeBytes emits a safe byte slice.
|
||||
SafeBytes(SafeBytes)
|
||||
|
||||
// Print emits its arguments separated by spaces.
|
||||
// For each argument it dynamically checks for the SafeFormatter or
|
||||
// SafeValue interface and either use that, or mark the argument
|
||||
@@ -119,6 +125,18 @@ type SafeRune rune
|
||||
// SafeValue makes SafeRune a SafeValue.
|
||||
func (SafeRune) SafeValue() {}
|
||||
|
||||
// SafeByte represents a byte that is not a sensitive value.
|
||||
type SafeByte byte
|
||||
|
||||
// SafeValue makes SafeByte a SafeValue.
|
||||
func (SafeByte) SafeValue() {}
|
||||
|
||||
// SafeBytes represents a byte slice that is not a sensitive value.
|
||||
type SafeBytes []byte
|
||||
|
||||
// SafeValue makes SafeBytes a SafeValue.
|
||||
func (SafeBytes) SafeValue() {}
|
||||
|
||||
// SafeValue is a marker interface to be implemented by types that
|
||||
// alias base Go types and whose natural representation via Printf is
|
||||
// always safe for reporting.
|
||||
|
||||
12
vendor/github.com/cockroachdb/redact/internal/rfmt/printer_adapter.go
generated
vendored
12
vendor/github.com/cockroachdb/redact/internal/rfmt/printer_adapter.go
generated
vendored
@@ -46,6 +46,18 @@ func (p *pp) SafeRune(r i.SafeRune) {
|
||||
p.buf.WriteRune(rune(r))
|
||||
}
|
||||
|
||||
// SafeByte implements SafePrinter.
|
||||
func (p *pp) SafeByte(r i.SafeByte) {
|
||||
defer p.startSafeOverride().restore()
|
||||
p.buf.WriteByte(byte(r))
|
||||
}
|
||||
|
||||
// SafeBytes implements SafePrinter.
|
||||
func (p *pp) SafeBytes(r i.SafeBytes) {
|
||||
defer p.startSafeOverride().restore()
|
||||
p.buf.Write(r)
|
||||
}
|
||||
|
||||
func (p *pp) Print(args ...interface{}) {
|
||||
defer p.buf.SetMode(p.buf.GetMode())
|
||||
np := newPrinter()
|
||||
|
||||
27
vendor/github.com/getsentry/sentry-go/.craft.yml
generated
vendored
27
vendor/github.com/getsentry/sentry-go/.craft.yml
generated
vendored
@@ -8,6 +8,33 @@ targets:
|
||||
- name: github
|
||||
tagPrefix: otel/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: echo/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: fasthttp/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: fiber/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: gin/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: iris/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: negroni/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: logrus/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: slog/v
|
||||
tagOnly: true
|
||||
- name: github
|
||||
tagPrefix: zerolog/v
|
||||
tagOnly: true
|
||||
- name: registry
|
||||
sdks:
|
||||
github:getsentry/sentry-go:
|
||||
|
||||
96
vendor/github.com/getsentry/sentry-go/CHANGELOG.md
generated
vendored
96
vendor/github.com/getsentry/sentry-go/CHANGELOG.md
generated
vendored
@@ -1,5 +1,101 @@
|
||||
# Changelog
|
||||
|
||||
## 0.31.1
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.31.1.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Correct wrong module name for `sentry-go/logrus` ([#950](https://github.com/getsentry/sentry-go/pull/950))
|
||||
|
||||
## 0.31.0
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.31.0.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- Remove support for metrics. Read more about the end of the Metrics beta [here](https://sentry.zendesk.com/hc/en-us/articles/26369339769883-Metrics-Beta-Ended-on-October-7th). ([#914](https://github.com/getsentry/sentry-go/pull/914))
|
||||
|
||||
- Remove support for profiling. ([#915](https://github.com/getsentry/sentry-go/pull/915))
|
||||
|
||||
- Remove `Segment` field from the `User` struct. This field is no longer used in the Sentry product. ([#928](https://github.com/getsentry/sentry-go/pull/928))
|
||||
|
||||
- Every integration is now a separate module, reducing the binary size and number of dependencies. Once you update `sentry-go` to latest version, you'll need to `go get` the integration you want to use. For example, if you want to use the `echo` integration, you'll need to run `go get github.com/getsentry/sentry-go/echo` ([#919](github.com/getsentry/sentry-go/pull/919)).
|
||||
|
||||
### Features
|
||||
|
||||
Add the ability to override `hub` in `context` for integrations that use custom context. ([#931](https://github.com/getsentry/sentry-go/pull/931))
|
||||
|
||||
- Add `HubProvider` Hook for `sentrylogrus`, enabling dynamic Sentry hub allocation for each log entry or goroutine. ([#936](https://github.com/getsentry/sentry-go/pull/936))
|
||||
|
||||
This change enhances compatibility with Sentry's recommendation of using separate hubs per goroutine. To ensure a separate Sentry hub for each goroutine, configure the `HubProvider` like this:
|
||||
|
||||
```go
|
||||
hook, err := sentrylogrus.New(nil, sentry.ClientOptions{})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialize Sentry hook: %v", err)
|
||||
}
|
||||
|
||||
// Set a custom HubProvider to generate a new hub for each goroutine or log entry
|
||||
hook.SetHubProvider(func() *sentry.Hub {
|
||||
client, _ := sentry.NewClient(sentry.ClientOptions{})
|
||||
return sentry.NewHub(client, sentry.NewScope())
|
||||
})
|
||||
|
||||
logrus.AddHook(hook)
|
||||
```
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Add support for closing worker goroutines started by the `HTTPTranport` to prevent goroutine leaks. ([#894](https://github.com/getsentry/sentry-go/pull/894))
|
||||
|
||||
```go
|
||||
client, _ := sentry.NewClient()
|
||||
defer client.Close()
|
||||
```
|
||||
|
||||
Worker can be also closed by calling `Close()` method on the `HTTPTransport` instance. `Close` should be called after `Flush` and before terminating the program otherwise some events may be lost.
|
||||
|
||||
```go
|
||||
transport := sentry.NewHTTPTransport()
|
||||
defer transport.Close()
|
||||
```
|
||||
|
||||
### Misc
|
||||
|
||||
- Bump [gin-gonic/gin](https://github.com/gin-gonic/gin) to v1.9.1. ([#946](https://github.com/getsentry/sentry-go/pull/946))
|
||||
|
||||
## 0.30.0
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.30.0.
|
||||
|
||||
### Features
|
||||
|
||||
- Add `sentryzerolog` integration ([#857](https://github.com/getsentry/sentry-go/pull/857))
|
||||
- Add `sentryslog` integration ([#865](https://github.com/getsentry/sentry-go/pull/865))
|
||||
- Always set Mechanism Type to generic ([#896](https://github.com/getsentry/sentry-go/pull/897))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Prevent panic in `fasthttp` and `fiber` integration in case a malformed URL has to be parsed ([#912](https://github.com/getsentry/sentry-go/pull/912))
|
||||
|
||||
### Misc
|
||||
|
||||
Drop support for Go 1.18, 1.19 and 1.20. The currently supported Go versions are the last 3 stable releases: 1.23, 1.22 and 1.21.
|
||||
|
||||
## 0.29.1
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.29.1.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Correlate errors to the current trace ([#886](https://github.com/getsentry/sentry-go/pull/886))
|
||||
- Set the trace context when the transaction finishes ([#888](https://github.com/getsentry/sentry-go/pull/888))
|
||||
|
||||
### Misc
|
||||
|
||||
- Update the `sentrynegroni` integration to use the latest (v3.1.1) version of Negroni ([#885](https://github.com/getsentry/sentry-go/pull/885))
|
||||
|
||||
## 0.29.0
|
||||
|
||||
The Sentry SDK team is happy to announce the immediate availability of Sentry Go SDK v0.29.0.
|
||||
|
||||
7
vendor/github.com/getsentry/sentry-go/Makefile
generated
vendored
7
vendor/github.com/getsentry/sentry-go/Makefile
generated
vendored
@@ -58,9 +58,8 @@ test-coverage: $(COVERAGE_REPORT_DIR) clean-report-dir ## Test with coverage en
|
||||
mod-tidy: ## Check go.mod tidiness
|
||||
set -e ; \
|
||||
for dir in $(ALL_GO_MOD_DIRS); do \
|
||||
cd "$${dir}"; \
|
||||
echo ">>> Running 'go mod tidy' for module: $${dir}"; \
|
||||
go mod tidy -go=1.18 -compat=1.18; \
|
||||
(cd "$${dir}" && go mod tidy -go=1.21 -compat=1.21); \
|
||||
done; \
|
||||
git diff --exit-code;
|
||||
.PHONY: mod-tidy
|
||||
@@ -68,12 +67,12 @@ mod-tidy: ## Check go.mod tidiness
|
||||
vet: ## Run "go vet"
|
||||
set -e ; \
|
||||
for dir in $(ALL_GO_MOD_DIRS); do \
|
||||
cd "$${dir}"; \
|
||||
echo ">>> Running 'go vet' for module: $${dir}"; \
|
||||
go vet ./...; \
|
||||
(cd "$${dir}" && go vet ./...); \
|
||||
done;
|
||||
.PHONY: vet
|
||||
|
||||
|
||||
lint: ## Lint (using "golangci-lint")
|
||||
golangci-lint run
|
||||
.PHONY: lint
|
||||
|
||||
8
vendor/github.com/getsentry/sentry-go/README.md
generated
vendored
8
vendor/github.com/getsentry/sentry-go/README.md
generated
vendored
@@ -10,7 +10,7 @@
|
||||
|
||||
# Official Sentry SDK for Go
|
||||
|
||||
[](https://github.com/getsentry/sentry-go/actions?query=workflow%3Ago-workflow)
|
||||
[](https://github.com/getsentry/sentry-go/actions/workflows/test.yml)
|
||||
[](https://goreportcard.com/report/github.com/getsentry/sentry-go)
|
||||
[](https://discord.gg/Ww9hbqr)
|
||||
[](https://pkg.go.dev/github.com/getsentry/sentry-go)
|
||||
@@ -68,16 +68,20 @@ To get started, have a look at one of our [examples](_examples/):
|
||||
We also provide a [complete API reference](https://pkg.go.dev/github.com/getsentry/sentry-go).
|
||||
|
||||
For more detailed information about how to get the most out of `sentry-go`,
|
||||
checkout the official documentation:
|
||||
check out the official documentation:
|
||||
|
||||
- [Sentry Go SDK documentation](https://docs.sentry.io/platforms/go/)
|
||||
- Guides:
|
||||
- [net/http](https://docs.sentry.io/platforms/go/guides/http/)
|
||||
- [echo](https://docs.sentry.io/platforms/go/guides/echo/)
|
||||
- [fasthttp](https://docs.sentry.io/platforms/go/guides/fasthttp/)
|
||||
- [fiber](https://docs.sentry.io/platforms/go/guides/fiber/)
|
||||
- [gin](https://docs.sentry.io/platforms/go/guides/gin/)
|
||||
- [iris](https://docs.sentry.io/platforms/go/guides/iris/)
|
||||
- [logrus](https://docs.sentry.io/platforms/go/guides/logrus/)
|
||||
- [negroni](https://docs.sentry.io/platforms/go/guides/negroni/)
|
||||
- [slog](https://docs.sentry.io/platforms/go/guides/slog/)
|
||||
- [zerolog](https://docs.sentry.io/platforms/go/guides/zerolog/)
|
||||
|
||||
## Resources
|
||||
|
||||
|
||||
23
vendor/github.com/getsentry/sentry-go/client.go
generated
vendored
23
vendor/github.com/getsentry/sentry-go/client.go
generated
vendored
@@ -133,9 +133,6 @@ type ClientOptions struct {
|
||||
TracesSampleRate float64
|
||||
// Used to customize the sampling of traces, overrides TracesSampleRate.
|
||||
TracesSampler TracesSampler
|
||||
// The sample rate for profiling traces in the range [0.0, 1.0].
|
||||
// This is relative to TracesSampleRate - it is a ratio of profiled traces out of all sampled traces.
|
||||
ProfilesSampleRate float64
|
||||
// List of regexp strings that will be used to match against event's message
|
||||
// and if applicable, caught errors type and value.
|
||||
// If the match is found, then a whole event will be dropped.
|
||||
@@ -513,6 +510,14 @@ func (client *Client) Flush(timeout time.Duration) bool {
|
||||
return client.Transport.Flush(timeout)
|
||||
}
|
||||
|
||||
// Close clean up underlying Transport resources.
|
||||
//
|
||||
// Close should be called after Flush and before terminating the program
|
||||
// otherwise some events may be lost.
|
||||
func (client *Client) Close() {
|
||||
client.Transport.Close()
|
||||
}
|
||||
|
||||
// EventFromMessage creates an event from the given message string.
|
||||
func (client *Client) EventFromMessage(message string, level Level) *Event {
|
||||
if message == "" {
|
||||
@@ -590,14 +595,6 @@ func (client *Client) GetSDKIdentifier() string {
|
||||
return client.sdkIdentifier
|
||||
}
|
||||
|
||||
// reverse reverses the slice a in place.
|
||||
func reverse(a []Exception) {
|
||||
for i := len(a)/2 - 1; i >= 0; i-- {
|
||||
opp := len(a) - 1 - i
|
||||
a[i], a[opp] = a[opp], a[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (client *Client) processEvent(event *Event, hint *EventHint, scope EventModifier) *EventID {
|
||||
if event == nil {
|
||||
err := usageError{fmt.Errorf("%s called with nil event", callerFunctionName())}
|
||||
@@ -709,10 +706,6 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
|
||||
}
|
||||
}
|
||||
|
||||
if event.sdkMetaData.transactionProfile != nil {
|
||||
event.sdkMetaData.transactionProfile.UpdateFromEvent(event)
|
||||
}
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
|
||||
4
vendor/github.com/getsentry/sentry-go/dsn.go
generated
vendored
4
vendor/github.com/getsentry/sentry-go/dsn.go
generated
vendored
@@ -89,8 +89,8 @@ func NewDsn(rawURL string) (*Dsn, error) {
|
||||
|
||||
// Port
|
||||
var port int
|
||||
if parsedURL.Port() != "" {
|
||||
port, err = strconv.Atoi(parsedURL.Port())
|
||||
if p := parsedURL.Port(); p != "" {
|
||||
port, err = strconv.Atoi(p)
|
||||
if err != nil {
|
||||
return nil, &DsnParseError{"invalid port"}
|
||||
}
|
||||
|
||||
16
vendor/github.com/getsentry/sentry-go/dynamic_sampling_context.go
generated
vendored
16
vendor/github.com/getsentry/sentry-go/dynamic_sampling_context.go
generated
vendored
@@ -100,15 +100,17 @@ func (d DynamicSamplingContext) String() string {
|
||||
}
|
||||
members = append(members, member)
|
||||
}
|
||||
if len(members) > 0 {
|
||||
baggage, err := baggage.New(members...)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return baggage.String()
|
||||
|
||||
if len(members) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return ""
|
||||
baggage, err := baggage.New(members...)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return baggage.String()
|
||||
}
|
||||
|
||||
// Constructs a new DynamicSamplingContext using a scope and client. Accessing
|
||||
|
||||
13
vendor/github.com/getsentry/sentry-go/hub.go
generated
vendored
13
vendor/github.com/getsentry/sentry-go/hub.go
generated
vendored
@@ -294,8 +294,13 @@ func (hub *Hub) AddBreadcrumb(breadcrumb *Breadcrumb, hint *BreadcrumbHint) {
|
||||
}
|
||||
|
||||
max := client.options.MaxBreadcrumbs
|
||||
if max < 0 {
|
||||
switch {
|
||||
case max < 0:
|
||||
return
|
||||
case max == 0:
|
||||
max = defaultMaxBreadcrumbs
|
||||
case max > maxBreadcrumbs:
|
||||
max = maxBreadcrumbs
|
||||
}
|
||||
|
||||
if client.options.BeforeBreadcrumb != nil {
|
||||
@@ -308,12 +313,6 @@ func (hub *Hub) AddBreadcrumb(breadcrumb *Breadcrumb, hint *BreadcrumbHint) {
|
||||
}
|
||||
}
|
||||
|
||||
if max == 0 {
|
||||
max = defaultMaxBreadcrumbs
|
||||
} else if max > maxBreadcrumbs {
|
||||
max = maxBreadcrumbs
|
||||
}
|
||||
|
||||
hub.Scope().AddBreadcrumb(breadcrumb, max)
|
||||
}
|
||||
|
||||
|
||||
38
vendor/github.com/getsentry/sentry-go/interfaces.go
generated
vendored
38
vendor/github.com/getsentry/sentry-go/interfaces.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -18,16 +19,9 @@ const eventType = "event"
|
||||
// transactionType is the type of a transaction event.
|
||||
const transactionType = "transaction"
|
||||
|
||||
// profileType is the type of a profile event.
|
||||
// currently, profiles are always sent as part of a transaction event.
|
||||
const profileType = "profile"
|
||||
|
||||
// checkInType is the type of a check in event.
|
||||
const checkInType = "check_in"
|
||||
|
||||
// metricType is the type of a metric event.
|
||||
const metricType = "statsd"
|
||||
|
||||
// Level marks the severity of the event.
|
||||
type Level string
|
||||
|
||||
@@ -118,32 +112,27 @@ type User struct {
|
||||
IPAddress string `json:"ip_address,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Segment string `json:"segment,omitempty"`
|
||||
Data map[string]string `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func (u User) IsEmpty() bool {
|
||||
if len(u.ID) > 0 {
|
||||
if u.ID != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(u.Email) > 0 {
|
||||
if u.Email != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(u.IPAddress) > 0 {
|
||||
if u.IPAddress != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(u.Username) > 0 {
|
||||
if u.Username != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(u.Name) > 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(u.Segment) > 0 {
|
||||
if u.Name != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -195,6 +184,7 @@ func NewRequest(r *http.Request) *Request {
|
||||
// attach more than one Cookie header field.
|
||||
cookies = r.Header.Get("Cookie")
|
||||
|
||||
headers = make(map[string]string, len(r.Header))
|
||||
for k, v := range r.Header {
|
||||
headers[k] = strings.Join(v, ",")
|
||||
}
|
||||
@@ -238,8 +228,7 @@ type Mechanism struct {
|
||||
// SetUnhandled indicates that the exception is an unhandled exception, i.e.
|
||||
// from a panic.
|
||||
func (m *Mechanism) SetUnhandled() {
|
||||
h := false
|
||||
m.Handled = &h
|
||||
m.Handled = Pointer(false)
|
||||
}
|
||||
|
||||
// Exception specifies an error that occurred.
|
||||
@@ -255,8 +244,7 @@ type Exception struct {
|
||||
// SDKMetaData is a struct to stash data which is needed at some point in the SDK's event processing pipeline
|
||||
// but which shouldn't get send to Sentry.
|
||||
type SDKMetaData struct {
|
||||
dsc DynamicSamplingContext
|
||||
transactionProfile *profileInfo
|
||||
dsc DynamicSamplingContext
|
||||
}
|
||||
|
||||
// Contains information about how the name of the transaction was determined.
|
||||
@@ -324,7 +312,6 @@ type Event struct {
|
||||
Exception []Exception `json:"exception,omitempty"`
|
||||
DebugMeta *DebugMeta `json:"debug_meta,omitempty"`
|
||||
Attachments []*Attachment `json:"-"`
|
||||
Metrics []Metric `json:"-"`
|
||||
|
||||
// The fields below are only relevant for transactions.
|
||||
|
||||
@@ -398,12 +385,13 @@ func (e *Event) SetException(exception error, maxErrorDepth int) {
|
||||
}
|
||||
|
||||
// event.Exception should be sorted such that the most recent error is last.
|
||||
reverse(e.Exception)
|
||||
slices.Reverse(e.Exception)
|
||||
|
||||
for i := range e.Exception {
|
||||
e.Exception[i].Mechanism = &Mechanism{
|
||||
IsExceptionGroup: true,
|
||||
ExceptionID: i,
|
||||
Type: "generic",
|
||||
}
|
||||
if i == 0 {
|
||||
continue
|
||||
@@ -429,7 +417,9 @@ func (e *Event) MarshalJSON() ([]byte, error) {
|
||||
// and a few type tricks.
|
||||
if e.Type == transactionType {
|
||||
return e.transactionMarshalJSON()
|
||||
} else if e.Type == checkInType {
|
||||
}
|
||||
|
||||
if e.Type == checkInType {
|
||||
return e.checkInMarshalJSON()
|
||||
}
|
||||
return e.defaultMarshalJSON()
|
||||
|
||||
15
vendor/github.com/getsentry/sentry-go/internal/traceparser/README.md
generated
vendored
15
vendor/github.com/getsentry/sentry-go/internal/traceparser/README.md
generated
vendored
@@ -1,15 +0,0 @@
|
||||
## Benchmark results
|
||||
|
||||
```
|
||||
goos: windows
|
||||
goarch: amd64
|
||||
pkg: github.com/getsentry/sentry-go/internal/trace
|
||||
cpu: 12th Gen Intel(R) Core(TM) i7-12700K
|
||||
BenchmarkEqualBytes-20 44323621 26.08 ns/op
|
||||
BenchmarkStringEqual-20 60980257 18.27 ns/op
|
||||
BenchmarkEqualPrefix-20 41369181 31.12 ns/op
|
||||
BenchmarkFullParse-20 702012 1507 ns/op 1353.42 MB/s 1024 B/op 6 allocs/op
|
||||
BenchmarkFramesIterator-20 1229971 969.3 ns/op 896 B/op 5 allocs/op
|
||||
BenchmarkFramesReversedIterator-20 1271061 944.5 ns/op 896 B/op 5 allocs/op
|
||||
BenchmarkSplitOnly-20 2250800 534.0 ns/op 3818.23 MB/s 128 B/op 1 allocs/op
|
||||
```
|
||||
217
vendor/github.com/getsentry/sentry-go/internal/traceparser/parser.go
generated
vendored
217
vendor/github.com/getsentry/sentry-go/internal/traceparser/parser.go
generated
vendored
@@ -1,217 +0,0 @@
|
||||
package traceparser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var blockSeparator = []byte("\n\n")
|
||||
var lineSeparator = []byte("\n")
|
||||
|
||||
// Parses multi-stacktrace text dump produced by runtime.Stack([]byte, all=true).
|
||||
// The parser prioritizes performance but requires the input to be well-formed in order to return correct data.
|
||||
// See https://github.com/golang/go/blob/go1.20.4/src/runtime/mprof.go#L1191
|
||||
func Parse(data []byte) TraceCollection {
|
||||
var it = TraceCollection{}
|
||||
if len(data) > 0 {
|
||||
it.blocks = bytes.Split(data, blockSeparator)
|
||||
}
|
||||
return it
|
||||
}
|
||||
|
||||
type TraceCollection struct {
|
||||
blocks [][]byte
|
||||
}
|
||||
|
||||
func (it TraceCollection) Length() int {
|
||||
return len(it.blocks)
|
||||
}
|
||||
|
||||
// Returns the stacktrace item at the given index.
|
||||
func (it *TraceCollection) Item(i int) Trace {
|
||||
// The first item may have a leading data separator and the last one may have a trailing one.
|
||||
// Note: Trim() doesn't make a copy for single-character cutset under 0x80. It will just slice the original.
|
||||
var data []byte
|
||||
switch {
|
||||
case i == 0:
|
||||
data = bytes.TrimLeft(it.blocks[i], "\n")
|
||||
case i == len(it.blocks)-1:
|
||||
data = bytes.TrimRight(it.blocks[i], "\n")
|
||||
default:
|
||||
data = it.blocks[i]
|
||||
}
|
||||
|
||||
var splitAt = bytes.IndexByte(data, '\n')
|
||||
if splitAt < 0 {
|
||||
return Trace{header: data}
|
||||
}
|
||||
|
||||
return Trace{
|
||||
header: data[:splitAt],
|
||||
data: data[splitAt+1:],
|
||||
}
|
||||
}
|
||||
|
||||
// Trace represents a single stacktrace block, identified by a Goroutine ID and a sequence of Frames.
|
||||
type Trace struct {
|
||||
header []byte
|
||||
data []byte
|
||||
}
|
||||
|
||||
var goroutinePrefix = []byte("goroutine ")
|
||||
|
||||
// GoID parses the Goroutine ID from the header.
|
||||
func (t *Trace) GoID() (id uint64) {
|
||||
if bytes.HasPrefix(t.header, goroutinePrefix) {
|
||||
var line = t.header[len(goroutinePrefix):]
|
||||
var splitAt = bytes.IndexByte(line, ' ')
|
||||
if splitAt >= 0 {
|
||||
id, _ = strconv.ParseUint(string(line[:splitAt]), 10, 64)
|
||||
}
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// UniqueIdentifier can be used as a map key to identify the trace.
|
||||
func (t *Trace) UniqueIdentifier() []byte {
|
||||
return t.data
|
||||
}
|
||||
|
||||
func (t *Trace) Frames() FrameIterator {
|
||||
var lines = bytes.Split(t.data, lineSeparator)
|
||||
return FrameIterator{lines: lines, i: 0, len: len(lines)}
|
||||
}
|
||||
|
||||
func (t *Trace) FramesReversed() ReverseFrameIterator {
|
||||
var lines = bytes.Split(t.data, lineSeparator)
|
||||
return ReverseFrameIterator{lines: lines, i: len(lines)}
|
||||
}
|
||||
|
||||
const framesElided = "...additional frames elided..."
|
||||
|
||||
// FrameIterator iterates over stack frames.
|
||||
type FrameIterator struct {
|
||||
lines [][]byte
|
||||
i int
|
||||
len int
|
||||
}
|
||||
|
||||
// Next returns the next frame, or nil if there are none.
|
||||
func (it *FrameIterator) Next() Frame {
|
||||
return Frame{it.popLine(), it.popLine()}
|
||||
}
|
||||
|
||||
func (it *FrameIterator) popLine() []byte {
|
||||
switch {
|
||||
case it.i >= it.len:
|
||||
return nil
|
||||
case string(it.lines[it.i]) == framesElided:
|
||||
it.i++
|
||||
return it.popLine()
|
||||
default:
|
||||
it.i++
|
||||
return it.lines[it.i-1]
|
||||
}
|
||||
}
|
||||
|
||||
// HasNext return true if there are values to be read.
|
||||
func (it *FrameIterator) HasNext() bool {
|
||||
return it.i < it.len
|
||||
}
|
||||
|
||||
// LengthUpperBound returns the maximum number of elements this stacks may contain.
|
||||
// The actual number may be lower because of elided frames. As such, the returned value
|
||||
// cannot be used to iterate over the frames but may be used to reserve capacity.
|
||||
func (it *FrameIterator) LengthUpperBound() int {
|
||||
return it.len / 2
|
||||
}
|
||||
|
||||
// ReverseFrameIterator iterates over stack frames in reverse order.
|
||||
type ReverseFrameIterator struct {
|
||||
lines [][]byte
|
||||
i int
|
||||
}
|
||||
|
||||
// Next returns the next frame, or nil if there are none.
|
||||
func (it *ReverseFrameIterator) Next() Frame {
|
||||
var line2 = it.popLine()
|
||||
return Frame{it.popLine(), line2}
|
||||
}
|
||||
|
||||
func (it *ReverseFrameIterator) popLine() []byte {
|
||||
it.i--
|
||||
switch {
|
||||
case it.i < 0:
|
||||
return nil
|
||||
case string(it.lines[it.i]) == framesElided:
|
||||
return it.popLine()
|
||||
default:
|
||||
return it.lines[it.i]
|
||||
}
|
||||
}
|
||||
|
||||
// HasNext return true if there are values to be read.
|
||||
func (it *ReverseFrameIterator) HasNext() bool {
|
||||
return it.i > 1
|
||||
}
|
||||
|
||||
// LengthUpperBound returns the maximum number of elements this stacks may contain.
|
||||
// The actual number may be lower because of elided frames. As such, the returned value
|
||||
// cannot be used to iterate over the frames but may be used to reserve capacity.
|
||||
func (it *ReverseFrameIterator) LengthUpperBound() int {
|
||||
return len(it.lines) / 2
|
||||
}
|
||||
|
||||
type Frame struct {
|
||||
line1 []byte
|
||||
line2 []byte
|
||||
}
|
||||
|
||||
// UniqueIdentifier can be used as a map key to identify the frame.
|
||||
func (f *Frame) UniqueIdentifier() []byte {
|
||||
// line2 contains file path, line number and program-counter offset from the beginning of a function
|
||||
// e.g. C:/Users/name/scoop/apps/go/current/src/testing/testing.go:1906 +0x63a
|
||||
return f.line2
|
||||
}
|
||||
|
||||
var createdByPrefix = []byte("created by ")
|
||||
|
||||
func (f *Frame) Func() []byte {
|
||||
if bytes.HasPrefix(f.line1, createdByPrefix) {
|
||||
// Since go1.21, the line ends with " in goroutine X", saying which goroutine created this one.
|
||||
// We currently don't have use for that so just remove it.
|
||||
var line = f.line1[len(createdByPrefix):]
|
||||
var spaceAt = bytes.IndexByte(line, ' ')
|
||||
if spaceAt < 0 {
|
||||
return line
|
||||
}
|
||||
return line[:spaceAt]
|
||||
}
|
||||
|
||||
var end = bytes.LastIndexByte(f.line1, '(')
|
||||
if end >= 0 {
|
||||
return f.line1[:end]
|
||||
}
|
||||
|
||||
return f.line1
|
||||
}
|
||||
|
||||
func (f *Frame) File() (path []byte, lineNumber int) {
|
||||
var line = f.line2
|
||||
if len(line) > 0 && line[0] == '\t' {
|
||||
line = line[1:]
|
||||
}
|
||||
|
||||
var splitAt = bytes.IndexByte(line, ' ')
|
||||
if splitAt >= 0 {
|
||||
line = line[:splitAt]
|
||||
}
|
||||
|
||||
splitAt = bytes.LastIndexByte(line, ':')
|
||||
if splitAt < 0 {
|
||||
return line, 0
|
||||
}
|
||||
|
||||
lineNumber, _ = strconv.Atoi(string(line[splitAt+1:]))
|
||||
return line[:splitAt], lineNumber
|
||||
}
|
||||
427
vendor/github.com/getsentry/sentry-go/metrics.go
generated
vendored
427
vendor/github.com/getsentry/sentry-go/metrics.go
generated
vendored
@@ -1,427 +0,0 @@
|
||||
package sentry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"math"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
NumberOrString interface {
|
||||
int | string
|
||||
}
|
||||
|
||||
void struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
member void
|
||||
keyRegex = regexp.MustCompile(`[^a-zA-Z0-9_/.-]+`)
|
||||
valueRegex = regexp.MustCompile(`[^\w\d\s_:/@\.{}\[\]$-]+`)
|
||||
unitRegex = regexp.MustCompile(`[^a-z]+`)
|
||||
)
|
||||
|
||||
type MetricUnit struct {
|
||||
unit string
|
||||
}
|
||||
|
||||
func (m MetricUnit) toString() string {
|
||||
return m.unit
|
||||
}
|
||||
|
||||
func NanoSecond() MetricUnit {
|
||||
return MetricUnit{
|
||||
"nanosecond",
|
||||
}
|
||||
}
|
||||
|
||||
func MicroSecond() MetricUnit {
|
||||
return MetricUnit{
|
||||
"microsecond",
|
||||
}
|
||||
}
|
||||
|
||||
func MilliSecond() MetricUnit {
|
||||
return MetricUnit{
|
||||
"millisecond",
|
||||
}
|
||||
}
|
||||
|
||||
func Second() MetricUnit {
|
||||
return MetricUnit{
|
||||
"second",
|
||||
}
|
||||
}
|
||||
|
||||
func Minute() MetricUnit {
|
||||
return MetricUnit{
|
||||
"minute",
|
||||
}
|
||||
}
|
||||
|
||||
func Hour() MetricUnit {
|
||||
return MetricUnit{
|
||||
"hour",
|
||||
}
|
||||
}
|
||||
|
||||
func Day() MetricUnit {
|
||||
return MetricUnit{
|
||||
"day",
|
||||
}
|
||||
}
|
||||
|
||||
func Week() MetricUnit {
|
||||
return MetricUnit{
|
||||
"week",
|
||||
}
|
||||
}
|
||||
|
||||
func Bit() MetricUnit {
|
||||
return MetricUnit{
|
||||
"bit",
|
||||
}
|
||||
}
|
||||
|
||||
func Byte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"byte",
|
||||
}
|
||||
}
|
||||
|
||||
func KiloByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"kilobyte",
|
||||
}
|
||||
}
|
||||
|
||||
func KibiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"kibibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func MegaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"megabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func MebiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"mebibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func GigaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"gigabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func GibiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"gibibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func TeraByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"terabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func TebiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"tebibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func PetaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"petabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func PebiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"pebibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func ExaByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"exabyte",
|
||||
}
|
||||
}
|
||||
|
||||
func ExbiByte() MetricUnit {
|
||||
return MetricUnit{
|
||||
"exbibyte",
|
||||
}
|
||||
}
|
||||
|
||||
func Ratio() MetricUnit {
|
||||
return MetricUnit{
|
||||
"ratio",
|
||||
}
|
||||
}
|
||||
|
||||
func Percent() MetricUnit {
|
||||
return MetricUnit{
|
||||
"percent",
|
||||
}
|
||||
}
|
||||
|
||||
func CustomUnit(unit string) MetricUnit {
|
||||
return MetricUnit{
|
||||
unitRegex.ReplaceAllString(unit, ""),
|
||||
}
|
||||
}
|
||||
|
||||
type Metric interface {
|
||||
GetType() string
|
||||
GetTags() map[string]string
|
||||
GetKey() string
|
||||
GetUnit() string
|
||||
GetTimestamp() int64
|
||||
SerializeValue() string
|
||||
SerializeTags() string
|
||||
}
|
||||
|
||||
type abstractMetric struct {
|
||||
key string
|
||||
unit MetricUnit
|
||||
tags map[string]string
|
||||
// A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
timestamp int64
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetTags() map[string]string {
|
||||
return am.tags
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetKey() string {
|
||||
return am.key
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetUnit() string {
|
||||
return am.unit.toString()
|
||||
}
|
||||
|
||||
func (am abstractMetric) GetTimestamp() int64 {
|
||||
return am.timestamp
|
||||
}
|
||||
|
||||
func (am abstractMetric) SerializeTags() string {
|
||||
var sb strings.Builder
|
||||
|
||||
values := make([]string, 0, len(am.tags))
|
||||
for k := range am.tags {
|
||||
values = append(values, k)
|
||||
}
|
||||
sortSlice(values)
|
||||
|
||||
for _, key := range values {
|
||||
val := sanitizeValue(am.tags[key])
|
||||
key = sanitizeKey(key)
|
||||
sb.WriteString(fmt.Sprintf("%s:%s,", key, val))
|
||||
}
|
||||
s := sb.String()
|
||||
if len(s) > 0 {
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Counter Metric.
|
||||
type CounterMetric struct {
|
||||
value float64
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (c *CounterMetric) Add(value float64) {
|
||||
c.value += value
|
||||
}
|
||||
|
||||
func (c CounterMetric) GetType() string {
|
||||
return "c"
|
||||
}
|
||||
|
||||
func (c CounterMetric) SerializeValue() string {
|
||||
return fmt.Sprintf(":%v", c.value)
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewCounterMetric(key string, unit MetricUnit, tags map[string]string, timestamp int64, value float64) CounterMetric {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return CounterMetric{
|
||||
value,
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
// Distribution Metric.
|
||||
type DistributionMetric struct {
|
||||
values []float64
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (d *DistributionMetric) Add(value float64) {
|
||||
d.values = append(d.values, value)
|
||||
}
|
||||
|
||||
func (d DistributionMetric) GetType() string {
|
||||
return "d"
|
||||
}
|
||||
|
||||
func (d DistributionMetric) SerializeValue() string {
|
||||
var sb strings.Builder
|
||||
for _, el := range d.values {
|
||||
sb.WriteString(fmt.Sprintf(":%v", el))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewDistributionMetric(key string, unit MetricUnit, tags map[string]string, timestamp int64, value float64) DistributionMetric {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return DistributionMetric{
|
||||
[]float64{value},
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
// Gauge Metric.
|
||||
type GaugeMetric struct {
|
||||
last float64
|
||||
min float64
|
||||
max float64
|
||||
sum float64
|
||||
count float64
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (g *GaugeMetric) Add(value float64) {
|
||||
g.last = value
|
||||
g.min = math.Min(g.min, value)
|
||||
g.max = math.Max(g.max, value)
|
||||
g.sum += value
|
||||
g.count++
|
||||
}
|
||||
|
||||
func (g GaugeMetric) GetType() string {
|
||||
return "g"
|
||||
}
|
||||
|
||||
func (g GaugeMetric) SerializeValue() string {
|
||||
return fmt.Sprintf(":%v:%v:%v:%v:%v", g.last, g.min, g.max, g.sum, g.count)
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewGaugeMetric(key string, unit MetricUnit, tags map[string]string, timestamp int64, value float64) GaugeMetric {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return GaugeMetric{
|
||||
value, // last
|
||||
value, // min
|
||||
value, // max
|
||||
value, // sum
|
||||
value, // count
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
// Set Metric.
|
||||
type SetMetric[T NumberOrString] struct {
|
||||
values map[T]void
|
||||
abstractMetric
|
||||
}
|
||||
|
||||
func (s *SetMetric[T]) Add(value T) {
|
||||
s.values[value] = member
|
||||
}
|
||||
|
||||
func (s SetMetric[T]) GetType() string {
|
||||
return "s"
|
||||
}
|
||||
|
||||
func (s SetMetric[T]) SerializeValue() string {
|
||||
_hash := func(s string) uint32 {
|
||||
return crc32.ChecksumIEEE([]byte(s))
|
||||
}
|
||||
|
||||
values := make([]T, 0, len(s.values))
|
||||
for k := range s.values {
|
||||
values = append(values, k)
|
||||
}
|
||||
sortSlice(values)
|
||||
|
||||
var sb strings.Builder
|
||||
for _, el := range values {
|
||||
switch any(el).(type) {
|
||||
case int:
|
||||
sb.WriteString(fmt.Sprintf(":%v", el))
|
||||
case string:
|
||||
s := fmt.Sprintf("%v", el)
|
||||
sb.WriteString(fmt.Sprintf(":%d", _hash(s)))
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// timestamp: A unix timestamp (full seconds elapsed since 1970-01-01 00:00 UTC).
|
||||
func NewSetMetric[T NumberOrString](key string, unit MetricUnit, tags map[string]string, timestamp int64, value T) SetMetric[T] {
|
||||
am := abstractMetric{
|
||||
key,
|
||||
unit,
|
||||
tags,
|
||||
timestamp,
|
||||
}
|
||||
|
||||
return SetMetric[T]{
|
||||
map[T]void{
|
||||
value: member,
|
||||
},
|
||||
am,
|
||||
}
|
||||
}
|
||||
|
||||
func sanitizeKey(s string) string {
|
||||
return keyRegex.ReplaceAllString(s, "_")
|
||||
}
|
||||
|
||||
func sanitizeValue(s string) string {
|
||||
return valueRegex.ReplaceAllString(s, "")
|
||||
}
|
||||
|
||||
type Ordered interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~string
|
||||
}
|
||||
|
||||
func sortSlice[T Ordered](s []T) {
|
||||
sort.Slice(s, func(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
})
|
||||
}
|
||||
73
vendor/github.com/getsentry/sentry-go/profile_sample.go
generated
vendored
73
vendor/github.com/getsentry/sentry-go/profile_sample.go
generated
vendored
@@ -1,73 +0,0 @@
|
||||
package sentry
|
||||
|
||||
// Based on https://github.com/getsentry/vroom/blob/d11c26063e802d66b9a592c4010261746ca3dfa4/internal/sample/sample.go
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
profileDevice struct {
|
||||
Architecture string `json:"architecture"`
|
||||
Classification string `json:"classification"`
|
||||
Locale string `json:"locale"`
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
Model string `json:"model"`
|
||||
}
|
||||
|
||||
profileOS struct {
|
||||
BuildNumber string `json:"build_number"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
profileRuntime struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
profileSample struct {
|
||||
ElapsedSinceStartNS uint64 `json:"elapsed_since_start_ns"`
|
||||
StackID int `json:"stack_id"`
|
||||
ThreadID uint64 `json:"thread_id"`
|
||||
}
|
||||
|
||||
profileThreadMetadata struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Priority int `json:"priority,omitempty"`
|
||||
}
|
||||
|
||||
profileStack []int
|
||||
|
||||
profileTrace struct {
|
||||
Frames []*Frame `json:"frames"`
|
||||
Samples []profileSample `json:"samples"`
|
||||
Stacks []profileStack `json:"stacks"`
|
||||
ThreadMetadata map[uint64]*profileThreadMetadata `json:"thread_metadata"`
|
||||
}
|
||||
|
||||
profileInfo struct {
|
||||
DebugMeta *DebugMeta `json:"debug_meta,omitempty"`
|
||||
Device profileDevice `json:"device"`
|
||||
Environment string `json:"environment,omitempty"`
|
||||
EventID string `json:"event_id"`
|
||||
OS profileOS `json:"os"`
|
||||
Platform string `json:"platform"`
|
||||
Release string `json:"release"`
|
||||
Dist string `json:"dist"`
|
||||
Runtime profileRuntime `json:"runtime"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Trace *profileTrace `json:"profile"`
|
||||
Transaction profileTransaction `json:"transaction"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// see https://github.com/getsentry/vroom/blob/a91e39416723ec44fc54010257020eeaf9a77cbd/internal/transaction/transaction.go
|
||||
profileTransaction struct {
|
||||
ActiveThreadID uint64 `json:"active_thread_id"`
|
||||
DurationNS uint64 `json:"duration_ns,omitempty"`
|
||||
ID EventID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TraceID string `json:"trace_id"`
|
||||
}
|
||||
)
|
||||
451
vendor/github.com/getsentry/sentry-go/profiler.go
generated
vendored
451
vendor/github.com/getsentry/sentry-go/profiler.go
generated
vendored
@@ -1,451 +0,0 @@
|
||||
package sentry
|
||||
|
||||
import (
|
||||
"container/ring"
|
||||
"strconv"
|
||||
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go/internal/traceparser"
|
||||
)
|
||||
|
||||
// Start a profiler that collects samples continuously, with a buffer of up to 30 seconds.
|
||||
// Later, you can collect a slice from this buffer, producing a Trace.
|
||||
func startProfiling(startTime time.Time) profiler {
|
||||
onProfilerStart()
|
||||
|
||||
p := newProfiler(startTime)
|
||||
|
||||
// Wait for the profiler to finish setting up before returning to the caller.
|
||||
started := make(chan struct{})
|
||||
go p.run(started)
|
||||
|
||||
if _, ok := <-started; ok {
|
||||
return p
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type profiler interface {
|
||||
// GetSlice returns a slice of the profiled data between the given times.
|
||||
GetSlice(startTime, endTime time.Time) *profilerResult
|
||||
Stop(wait bool)
|
||||
}
|
||||
|
||||
type profilerResult struct {
|
||||
callerGoID uint64
|
||||
trace *profileTrace
|
||||
}
|
||||
|
||||
func getCurrentGoID() uint64 {
|
||||
// We shouldn't panic but let's be super safe.
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
Logger.Printf("Profiler panic in getCurrentGoID(): %v\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Buffer to read the stack trace into. We should be good with a small buffer because we only need the first line.
|
||||
var stacksBuffer = make([]byte, 100)
|
||||
var n = runtime.Stack(stacksBuffer, false)
|
||||
if n > 0 {
|
||||
var traces = traceparser.Parse(stacksBuffer[0:n])
|
||||
if traces.Length() > 0 {
|
||||
var trace = traces.Item(0)
|
||||
return trace.GoID()
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
const profilerSamplingRateHz = 101 // 101 Hz; not 100 Hz because of the lockstep sampling (https://stackoverflow.com/a/45471031/1181370)
|
||||
const profilerSamplingRate = time.Second / profilerSamplingRateHz
|
||||
const stackBufferMaxGrowth = 512 * 1024
|
||||
const stackBufferLimit = 10 * 1024 * 1024
|
||||
const profilerRuntimeLimit = 30 // seconds
|
||||
|
||||
type profileRecorder struct {
|
||||
startTime time.Time
|
||||
stopSignal chan struct{}
|
||||
stopped int64
|
||||
mutex sync.RWMutex
|
||||
testProfilerPanic int64
|
||||
|
||||
// Map from runtime.StackRecord.Stack0 to an index in stacks.
|
||||
stackIndexes map[string]int
|
||||
stacks []profileStack
|
||||
newStacks []profileStack // New stacks created in the current interation.
|
||||
stackKeyBuffer []byte
|
||||
|
||||
// Map from runtime.Frame.PC to an index in frames.
|
||||
frameIndexes map[string]int
|
||||
frames []*Frame
|
||||
newFrames []*Frame // New frames created in the current interation.
|
||||
|
||||
// We keep a ring buffer of 30 seconds worth of samples, so that we can later slice it.
|
||||
// Each bucket is a slice of samples all taken at the same time.
|
||||
samplesBucketsHead *ring.Ring
|
||||
|
||||
// Buffer to read current stacks - will grow automatically up to stackBufferLimit.
|
||||
stacksBuffer []byte
|
||||
}
|
||||
|
||||
func newProfiler(startTime time.Time) *profileRecorder {
|
||||
// Pre-allocate the profile trace for the currently active number of routines & 100 ms worth of samples.
|
||||
// Other coefficients are just guesses of what might be a good starting point to avoid allocs on short runs.
|
||||
return &profileRecorder{
|
||||
startTime: startTime,
|
||||
stopSignal: make(chan struct{}, 1),
|
||||
|
||||
stackIndexes: make(map[string]int, 32),
|
||||
stacks: make([]profileStack, 0, 32),
|
||||
newStacks: make([]profileStack, 0, 32),
|
||||
|
||||
frameIndexes: make(map[string]int, 128),
|
||||
frames: make([]*Frame, 0, 128),
|
||||
newFrames: make([]*Frame, 0, 128),
|
||||
|
||||
samplesBucketsHead: ring.New(profilerRuntimeLimit * profilerSamplingRateHz),
|
||||
|
||||
// A buffer of 2 KiB per goroutine stack looks like a good starting point (empirically determined).
|
||||
stacksBuffer: make([]byte, runtime.NumGoroutine()*2048),
|
||||
}
|
||||
}
|
||||
|
||||
// This allows us to test whether panic during profiling are handled correctly and don't block execution.
|
||||
// If the number is lower than 0, profilerGoroutine() will panic immedately.
|
||||
// If the number is higher than 0, profiler.onTick() will panic when the given samples-set index is being collected.
|
||||
var testProfilerPanic int64
|
||||
var profilerRunning int64
|
||||
|
||||
func (p *profileRecorder) run(started chan struct{}) {
|
||||
// Code backup for manual test debugging:
|
||||
// if !atomic.CompareAndSwapInt64(&profilerRunning, 0, 1) {
|
||||
// panic("Only one profiler can be running at a time")
|
||||
// }
|
||||
|
||||
// We shouldn't panic but let's be super safe.
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
Logger.Printf("Profiler panic in run(): %v\n", err)
|
||||
}
|
||||
atomic.StoreInt64(&testProfilerPanic, 0)
|
||||
close(started)
|
||||
p.stopSignal <- struct{}{}
|
||||
atomic.StoreInt64(&p.stopped, 1)
|
||||
atomic.StoreInt64(&profilerRunning, 0)
|
||||
}()
|
||||
|
||||
p.testProfilerPanic = atomic.LoadInt64(&testProfilerPanic)
|
||||
if p.testProfilerPanic < 0 {
|
||||
Logger.Printf("Profiler panicking during startup because testProfilerPanic == %v\n", p.testProfilerPanic)
|
||||
panic("This is an expected panic in profilerGoroutine() during tests")
|
||||
}
|
||||
|
||||
// Collect the first sample immediately.
|
||||
p.onTick()
|
||||
|
||||
// Periodically collect stacks, starting after profilerSamplingRate has passed.
|
||||
collectTicker := profilerTickerFactory(profilerSamplingRate)
|
||||
defer collectTicker.Stop()
|
||||
var tickerChannel = collectTicker.TickSource()
|
||||
|
||||
started <- struct{}{}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-tickerChannel:
|
||||
p.onTick()
|
||||
collectTicker.Ticked()
|
||||
case <-p.stopSignal:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *profileRecorder) Stop(wait bool) {
|
||||
if atomic.LoadInt64(&p.stopped) == 1 {
|
||||
return
|
||||
}
|
||||
p.stopSignal <- struct{}{}
|
||||
if wait {
|
||||
<-p.stopSignal
|
||||
}
|
||||
}
|
||||
|
||||
func (p *profileRecorder) GetSlice(startTime, endTime time.Time) *profilerResult {
|
||||
// Unlikely edge cases - profiler wasn't running at all or the given times are invalid in relation to each other.
|
||||
if p.startTime.After(endTime) || startTime.After(endTime) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var relativeStartNS = uint64(0)
|
||||
if p.startTime.Before(startTime) {
|
||||
relativeStartNS = uint64(startTime.Sub(p.startTime).Nanoseconds())
|
||||
}
|
||||
var relativeEndNS = uint64(endTime.Sub(p.startTime).Nanoseconds())
|
||||
|
||||
samplesCount, bucketsReversed, trace := p.getBuckets(relativeStartNS, relativeEndNS)
|
||||
if samplesCount == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result = &profilerResult{
|
||||
callerGoID: getCurrentGoID(),
|
||||
trace: trace,
|
||||
}
|
||||
|
||||
trace.Samples = make([]profileSample, samplesCount)
|
||||
trace.ThreadMetadata = make(map[uint64]*profileThreadMetadata, len(bucketsReversed[0].goIDs))
|
||||
var s = samplesCount - 1
|
||||
for _, bucket := range bucketsReversed {
|
||||
var elapsedSinceStartNS = bucket.relativeTimeNS - relativeStartNS
|
||||
for i, goID := range bucket.goIDs {
|
||||
trace.Samples[s].ElapsedSinceStartNS = elapsedSinceStartNS
|
||||
trace.Samples[s].ThreadID = goID
|
||||
trace.Samples[s].StackID = bucket.stackIDs[i]
|
||||
s--
|
||||
|
||||
if _, goroutineExists := trace.ThreadMetadata[goID]; !goroutineExists {
|
||||
trace.ThreadMetadata[goID] = &profileThreadMetadata{
|
||||
Name: "Goroutine " + strconv.FormatUint(goID, 10),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Collect all buckets of samples in the given time range while holding a read lock.
|
||||
func (p *profileRecorder) getBuckets(relativeStartNS, relativeEndNS uint64) (samplesCount int, buckets []*profileSamplesBucket, trace *profileTrace) {
|
||||
p.mutex.RLock()
|
||||
defer p.mutex.RUnlock()
|
||||
|
||||
// sampleBucketsHead points at the last stored bucket so it's a good starting point to search backwards for the end.
|
||||
var end = p.samplesBucketsHead
|
||||
for end.Value != nil && end.Value.(*profileSamplesBucket).relativeTimeNS > relativeEndNS {
|
||||
end = end.Prev()
|
||||
}
|
||||
|
||||
// Edge case - no items stored before the given endTime.
|
||||
if end.Value == nil {
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
{ // Find the first item after the given startTime.
|
||||
var start = end
|
||||
var prevBucket *profileSamplesBucket
|
||||
samplesCount = 0
|
||||
buckets = make([]*profileSamplesBucket, 0, int64((relativeEndNS-relativeStartNS)/uint64(profilerSamplingRate.Nanoseconds()))+1)
|
||||
for start.Value != nil {
|
||||
var bucket = start.Value.(*profileSamplesBucket)
|
||||
|
||||
// If this bucket's time is before the requests start time, don't collect it (and stop iterating further).
|
||||
if bucket.relativeTimeNS < relativeStartNS {
|
||||
break
|
||||
}
|
||||
|
||||
// If this bucket time is greater than previous the bucket's time, we have exhausted the whole ring buffer
|
||||
// before we were able to find the start time. That means the start time is not present and we must break.
|
||||
// This happens if the slice duration exceeds the ring buffer capacity.
|
||||
if prevBucket != nil && bucket.relativeTimeNS > prevBucket.relativeTimeNS {
|
||||
break
|
||||
}
|
||||
|
||||
samplesCount += len(bucket.goIDs)
|
||||
buckets = append(buckets, bucket)
|
||||
|
||||
start = start.Prev()
|
||||
prevBucket = bucket
|
||||
}
|
||||
}
|
||||
|
||||
// Edge case - if the period requested was too short and we haven't collected enough samples.
|
||||
if len(buckets) < 2 {
|
||||
return 0, nil, nil
|
||||
}
|
||||
|
||||
trace = &profileTrace{
|
||||
Frames: p.frames,
|
||||
Stacks: p.stacks,
|
||||
}
|
||||
return samplesCount, buckets, trace
|
||||
}
|
||||
|
||||
func (p *profileRecorder) onTick() {
|
||||
elapsedNs := time.Since(p.startTime).Nanoseconds()
|
||||
|
||||
if p.testProfilerPanic > 0 {
|
||||
Logger.Printf("Profiler testProfilerPanic == %v\n", p.testProfilerPanic)
|
||||
if p.testProfilerPanic == 1 {
|
||||
Logger.Println("Profiler panicking onTick()")
|
||||
panic("This is an expected panic in Profiler.OnTick() during tests")
|
||||
}
|
||||
p.testProfilerPanic--
|
||||
}
|
||||
|
||||
records := p.collectRecords()
|
||||
p.processRecords(uint64(elapsedNs), records)
|
||||
|
||||
// Free up some memory if we don't need such a large buffer anymore.
|
||||
if len(p.stacksBuffer) > len(records)*3 {
|
||||
p.stacksBuffer = make([]byte, len(records)*3)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *profileRecorder) collectRecords() []byte {
|
||||
for {
|
||||
// Capture stacks for all existing goroutines.
|
||||
// Note: runtime.GoroutineProfile() would be better but we can't use it at the moment because
|
||||
// it doesn't give us `gid` for each routine, see https://github.com/golang/go/issues/59663
|
||||
n := runtime.Stack(p.stacksBuffer, true)
|
||||
|
||||
// If we couldn't read everything, increase the buffer and try again.
|
||||
if n >= len(p.stacksBuffer) && n < stackBufferLimit {
|
||||
var newSize = n * 2
|
||||
if newSize > n+stackBufferMaxGrowth {
|
||||
newSize = n + stackBufferMaxGrowth
|
||||
}
|
||||
if newSize > stackBufferLimit {
|
||||
newSize = stackBufferLimit
|
||||
}
|
||||
p.stacksBuffer = make([]byte, newSize)
|
||||
} else {
|
||||
return p.stacksBuffer[0:n]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *profileRecorder) processRecords(elapsedNs uint64, stacksBuffer []byte) {
|
||||
var traces = traceparser.Parse(stacksBuffer)
|
||||
var length = traces.Length()
|
||||
|
||||
// Shouldn't happen but let's be safe and don't store empty buckets.
|
||||
if length == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var bucket = &profileSamplesBucket{
|
||||
relativeTimeNS: elapsedNs,
|
||||
stackIDs: make([]int, length),
|
||||
goIDs: make([]uint64, length),
|
||||
}
|
||||
|
||||
// reset buffers
|
||||
p.newFrames = p.newFrames[:0]
|
||||
p.newStacks = p.newStacks[:0]
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
var stack = traces.Item(i)
|
||||
bucket.stackIDs[i] = p.addStackTrace(stack)
|
||||
bucket.goIDs[i] = stack.GoID()
|
||||
}
|
||||
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
|
||||
p.stacks = append(p.stacks, p.newStacks...)
|
||||
p.frames = append(p.frames, p.newFrames...)
|
||||
|
||||
p.samplesBucketsHead = p.samplesBucketsHead.Next()
|
||||
p.samplesBucketsHead.Value = bucket
|
||||
}
|
||||
|
||||
func (p *profileRecorder) addStackTrace(capturedStack traceparser.Trace) int {
|
||||
iter := capturedStack.Frames()
|
||||
stack := make(profileStack, 0, iter.LengthUpperBound())
|
||||
|
||||
// Originally, we've used `capturedStack.UniqueIdentifier()` as a key but that was incorrect because it also
|
||||
// contains function arguments and we want to group stacks by function name and file/line only.
|
||||
// Instead, we need to parse frames and we use a list of their indexes as a key.
|
||||
// We reuse the same buffer for each stack to avoid allocations; this is a hot spot.
|
||||
var expectedBufferLen = cap(stack) * 5 // 4 bytes per frame + 1 byte for space
|
||||
if cap(p.stackKeyBuffer) < expectedBufferLen {
|
||||
p.stackKeyBuffer = make([]byte, 0, expectedBufferLen)
|
||||
} else {
|
||||
p.stackKeyBuffer = p.stackKeyBuffer[:0]
|
||||
}
|
||||
|
||||
for iter.HasNext() {
|
||||
var frame = iter.Next()
|
||||
if frameIndex := p.addFrame(frame); frameIndex >= 0 {
|
||||
stack = append(stack, frameIndex)
|
||||
|
||||
p.stackKeyBuffer = append(p.stackKeyBuffer, 0) // space
|
||||
|
||||
// The following code is just like binary.AppendUvarint() which isn't yet available in Go 1.18.
|
||||
x := uint64(frameIndex) + 1
|
||||
for x >= 0x80 {
|
||||
p.stackKeyBuffer = append(p.stackKeyBuffer, byte(x)|0x80)
|
||||
x >>= 7
|
||||
}
|
||||
p.stackKeyBuffer = append(p.stackKeyBuffer, byte(x))
|
||||
}
|
||||
}
|
||||
|
||||
stackIndex, exists := p.stackIndexes[string(p.stackKeyBuffer)]
|
||||
if !exists {
|
||||
stackIndex = len(p.stacks) + len(p.newStacks)
|
||||
p.newStacks = append(p.newStacks, stack)
|
||||
p.stackIndexes[string(p.stackKeyBuffer)] = stackIndex
|
||||
}
|
||||
|
||||
return stackIndex
|
||||
}
|
||||
|
||||
func (p *profileRecorder) addFrame(capturedFrame traceparser.Frame) int {
|
||||
// NOTE: Don't convert to string yet, it's expensive and compiler can avoid it when
|
||||
// indexing into a map (only needs a copy when adding a new key to the map).
|
||||
var key = capturedFrame.UniqueIdentifier()
|
||||
|
||||
frameIndex, exists := p.frameIndexes[string(key)]
|
||||
if !exists {
|
||||
module, function := splitQualifiedFunctionName(string(capturedFrame.Func()))
|
||||
file, line := capturedFrame.File()
|
||||
frame := newFrame(module, function, string(file), line)
|
||||
frameIndex = len(p.frames) + len(p.newFrames)
|
||||
p.newFrames = append(p.newFrames, &frame)
|
||||
p.frameIndexes[string(key)] = frameIndex
|
||||
}
|
||||
return frameIndex
|
||||
}
|
||||
|
||||
type profileSamplesBucket struct {
|
||||
relativeTimeNS uint64
|
||||
stackIDs []int
|
||||
goIDs []uint64
|
||||
}
|
||||
|
||||
// A Ticker holds a channel that delivers “ticks” of a clock at intervals.
|
||||
type profilerTicker interface {
|
||||
// Stop turns off a ticker. After Stop, no more ticks will be sent.
|
||||
Stop()
|
||||
|
||||
// TickSource returns a read-only channel of ticks.
|
||||
TickSource() <-chan time.Time
|
||||
|
||||
// Ticked is called by the Profiler after a tick is processed to notify the ticker. Used for testing.
|
||||
Ticked()
|
||||
}
|
||||
|
||||
type timeTicker struct {
|
||||
*time.Ticker
|
||||
}
|
||||
|
||||
func (t *timeTicker) TickSource() <-chan time.Time {
|
||||
return t.C
|
||||
}
|
||||
|
||||
func (t *timeTicker) Ticked() {}
|
||||
|
||||
func profilerTickerFactoryDefault(d time.Duration) profilerTicker {
|
||||
return &timeTicker{time.NewTicker(d)}
|
||||
}
|
||||
|
||||
// We allow overriding the ticker for tests. CI is terribly flaky
|
||||
// because the time.Ticker doesn't guarantee regular ticks - they may come (a lot) later than the given interval.
|
||||
var profilerTickerFactory = profilerTickerFactoryDefault
|
||||
5
vendor/github.com/getsentry/sentry-go/profiler_other.go
generated
vendored
5
vendor/github.com/getsentry/sentry-go/profiler_other.go
generated
vendored
@@ -1,5 +0,0 @@
|
||||
//go:build !windows
|
||||
|
||||
package sentry
|
||||
|
||||
func onProfilerStart() {}
|
||||
24
vendor/github.com/getsentry/sentry-go/profiler_windows.go
generated
vendored
24
vendor/github.com/getsentry/sentry-go/profiler_windows.go
generated
vendored
@@ -1,24 +0,0 @@
|
||||
package sentry
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// This works around the ticker resolution on Windows being ~15ms by default.
|
||||
// See https://github.com/golang/go/issues/44343
|
||||
func setTimeTickerResolution() {
|
||||
var winmmDLL = syscall.NewLazyDLL("winmm.dll")
|
||||
if winmmDLL != nil {
|
||||
var timeBeginPeriod = winmmDLL.NewProc("timeBeginPeriod")
|
||||
if timeBeginPeriod != nil {
|
||||
timeBeginPeriod.Call(uintptr(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var setupTickerResolutionOnce sync.Once
|
||||
|
||||
func onProfilerStart() {
|
||||
setupTickerResolutionOnce.Do(setTimeTickerResolution)
|
||||
}
|
||||
15
vendor/github.com/getsentry/sentry-go/scope.go
generated
vendored
15
vendor/github.com/getsentry/sentry-go/scope.go
generated
vendored
@@ -383,6 +383,15 @@ func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint, client *Client)
|
||||
}
|
||||
|
||||
for key, value := range scope.contexts {
|
||||
if key == "trace" && event.Type == transactionType {
|
||||
// Do not override trace context of
|
||||
// transactions, otherwise it breaks the
|
||||
// transaction event representation.
|
||||
// For error events, the trace context is used
|
||||
// to link errors and traces/spans in Sentry.
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure we are not overwriting event fields
|
||||
if _, ok := event.Contexts[key]; !ok {
|
||||
event.Contexts[key] = cloneContext(value)
|
||||
@@ -395,7 +404,9 @@ func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint, client *Client)
|
||||
}
|
||||
|
||||
if scope.span != nil {
|
||||
event.Contexts["trace"] = scope.span.traceContext().Map()
|
||||
if _, ok := event.Contexts["trace"]; !ok {
|
||||
event.Contexts["trace"] = scope.span.traceContext().Map()
|
||||
}
|
||||
|
||||
transaction := scope.span.GetTransaction()
|
||||
if transaction != nil {
|
||||
@@ -467,7 +478,7 @@ func (scope *Scope) ApplyToEvent(event *Event, hint *EventHint, client *Client)
|
||||
// a proper deep copy: if some context values are pointer types (e.g. maps),
|
||||
// they won't be properly copied.
|
||||
func cloneContext(c Context) Context {
|
||||
res := Context{}
|
||||
res := make(Context, len(c))
|
||||
for k, v := range c {
|
||||
res[k] = v
|
||||
}
|
||||
|
||||
2
vendor/github.com/getsentry/sentry-go/sentry.go
generated
vendored
2
vendor/github.com/getsentry/sentry-go/sentry.go
generated
vendored
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
// The version of the SDK.
|
||||
const SDKVersion = "0.29.0"
|
||||
const SDKVersion = "0.31.1"
|
||||
|
||||
// apiVersion is the minimum version of the Sentry API compatible with the
|
||||
// sentry-go SDK.
|
||||
|
||||
43
vendor/github.com/getsentry/sentry-go/stacktrace.go
generated
vendored
43
vendor/github.com/getsentry/sentry-go/stacktrace.go
generated
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"go/build"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -277,12 +278,7 @@ func extractFrames(pcs []uintptr) []runtime.Frame {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO don't append and reverse, put in the right place from the start.
|
||||
// reverse
|
||||
for i, j := 0, len(frames)-1; i < j; i, j = i+1, j-1 {
|
||||
frames[i], frames[j] = frames[j], frames[i]
|
||||
}
|
||||
|
||||
slices.Reverse(frames)
|
||||
return frames
|
||||
}
|
||||
|
||||
@@ -336,12 +332,10 @@ func shouldSkipFrame(module string) bool {
|
||||
var goRoot = strings.ReplaceAll(build.Default.GOROOT, "\\", "/")
|
||||
|
||||
func setInAppFrame(frame *Frame) {
|
||||
if strings.HasPrefix(frame.AbsPath, goRoot) ||
|
||||
strings.Contains(frame.Module, "vendor") ||
|
||||
frame.InApp = true
|
||||
if strings.HasPrefix(frame.AbsPath, goRoot) || strings.Contains(frame.Module, "vendor") ||
|
||||
strings.Contains(frame.Module, "third_party") {
|
||||
frame.InApp = false
|
||||
} else {
|
||||
frame.InApp = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,3 +376,32 @@ func baseName(name string) string {
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func isCompilerGeneratedSymbol(name string) bool {
|
||||
// In versions of Go 1.20 and above a prefix of "type:" and "go:" is a
|
||||
// compiler-generated symbol that doesn't belong to any package.
|
||||
// See variable reservedimports in cmd/compile/internal/gc/subr.go
|
||||
if strings.HasPrefix(name, "go:") || strings.HasPrefix(name, "type:") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Walk backwards through the results and for the current function name
|
||||
// remove it's parent function's prefix, leaving only it's actual name. This
|
||||
// fixes issues grouping errors with the new fully qualified function names
|
||||
// introduced from Go 1.21.
|
||||
func cleanupFunctionNamePrefix(f []Frame) []Frame {
|
||||
for i := len(f) - 1; i > 0; i-- {
|
||||
name := f[i].Function
|
||||
parentName := f[i-1].Function + "."
|
||||
|
||||
if !strings.HasPrefix(name, parentName) {
|
||||
continue
|
||||
}
|
||||
|
||||
f[i].Function = name[len(parentName):]
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
15
vendor/github.com/getsentry/sentry-go/stacktrace_below_go1.20.go
generated
vendored
15
vendor/github.com/getsentry/sentry-go/stacktrace_below_go1.20.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
//go:build !go1.20
|
||||
|
||||
package sentry
|
||||
|
||||
import "strings"
|
||||
|
||||
func isCompilerGeneratedSymbol(name string) bool {
|
||||
// In versions of Go below 1.20 a prefix of "type." and "go." is a
|
||||
// compiler-generated symbol that doesn't belong to any package.
|
||||
// See variable reservedimports in cmd/compile/internal/gc/subr.go
|
||||
if strings.HasPrefix(name, "go.") || strings.HasPrefix(name, "type.") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
7
vendor/github.com/getsentry/sentry-go/stacktrace_below_go1.21.go
generated
vendored
7
vendor/github.com/getsentry/sentry-go/stacktrace_below_go1.21.go
generated
vendored
@@ -1,7 +0,0 @@
|
||||
//go:build !go1.21
|
||||
|
||||
package sentry
|
||||
|
||||
func cleanupFunctionNamePrefix(f []Frame) []Frame {
|
||||
return f
|
||||
}
|
||||
15
vendor/github.com/getsentry/sentry-go/stacktrace_go1.20.go
generated
vendored
15
vendor/github.com/getsentry/sentry-go/stacktrace_go1.20.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
//go:build go1.20
|
||||
|
||||
package sentry
|
||||
|
||||
import "strings"
|
||||
|
||||
func isCompilerGeneratedSymbol(name string) bool {
|
||||
// In versions of Go 1.20 and above a prefix of "type:" and "go:" is a
|
||||
// compiler-generated symbol that doesn't belong to any package.
|
||||
// See variable reservedimports in cmd/compile/internal/gc/subr.go
|
||||
if strings.HasPrefix(name, "go:") || strings.HasPrefix(name, "type:") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
25
vendor/github.com/getsentry/sentry-go/stacktrace_go1.21.go
generated
vendored
25
vendor/github.com/getsentry/sentry-go/stacktrace_go1.21.go
generated
vendored
@@ -1,25 +0,0 @@
|
||||
//go:build go1.21
|
||||
|
||||
package sentry
|
||||
|
||||
import "strings"
|
||||
|
||||
// Walk backwards through the results and for the current function name
|
||||
// remove it's parent function's prefix, leaving only it's actual name. This
|
||||
// fixes issues grouping errors with the new fully qualified function names
|
||||
// introduced from Go 1.21.
|
||||
|
||||
func cleanupFunctionNamePrefix(f []Frame) []Frame {
|
||||
for i := len(f) - 1; i > 0; i-- {
|
||||
name := f[i].Function
|
||||
parentName := f[i-1].Function + "."
|
||||
|
||||
if !strings.HasPrefix(name, parentName) {
|
||||
continue
|
||||
}
|
||||
|
||||
f[i].Function = name[len(parentName):]
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
95
vendor/github.com/getsentry/sentry-go/traces_profiler.go
generated
vendored
95
vendor/github.com/getsentry/sentry-go/traces_profiler.go
generated
vendored
@@ -1,95 +0,0 @@
|
||||
package sentry
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Checks whether the transaction should be profiled (according to ProfilesSampleRate)
|
||||
// and starts a profiler if so.
|
||||
func (s *Span) sampleTransactionProfile() {
|
||||
var sampleRate = s.clientOptions().ProfilesSampleRate
|
||||
switch {
|
||||
case sampleRate < 0.0 || sampleRate > 1.0:
|
||||
Logger.Printf("Skipping transaction profiling: ProfilesSampleRate out of range [0.0, 1.0]: %f\n", sampleRate)
|
||||
case sampleRate == 0.0 || rng.Float64() >= sampleRate:
|
||||
Logger.Printf("Skipping transaction profiling: ProfilesSampleRate is: %f\n", sampleRate)
|
||||
default:
|
||||
startProfilerOnce.Do(startGlobalProfiler)
|
||||
if globalProfiler == nil {
|
||||
Logger.Println("Skipping transaction profiling: the profiler couldn't be started")
|
||||
} else {
|
||||
s.collectProfile = collectTransactionProfile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// transactionProfiler collects a profile for a given span.
|
||||
type transactionProfiler func(span *Span) *profileInfo
|
||||
|
||||
var startProfilerOnce sync.Once
|
||||
var globalProfiler profiler
|
||||
|
||||
func startGlobalProfiler() {
|
||||
globalProfiler = startProfiling(time.Now())
|
||||
}
|
||||
|
||||
func collectTransactionProfile(span *Span) *profileInfo {
|
||||
result := globalProfiler.GetSlice(span.StartTime, span.EndTime)
|
||||
if result == nil || result.trace == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
info := &profileInfo{
|
||||
Version: "1",
|
||||
EventID: uuid(),
|
||||
// See https://github.com/getsentry/sentry-go/pull/626#discussion_r1204870340 for explanation why we use the Transaction time.
|
||||
Timestamp: span.StartTime,
|
||||
Trace: result.trace,
|
||||
Transaction: profileTransaction{
|
||||
DurationNS: uint64(span.EndTime.Sub(span.StartTime).Nanoseconds()),
|
||||
Name: span.Name,
|
||||
TraceID: span.TraceID.String(),
|
||||
},
|
||||
}
|
||||
if len(info.Transaction.Name) == 0 {
|
||||
// Name is required by Relay so use the operation name if the span name is empty.
|
||||
info.Transaction.Name = span.Op
|
||||
}
|
||||
if result.callerGoID > 0 {
|
||||
info.Transaction.ActiveThreadID = result.callerGoID
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
func (info *profileInfo) UpdateFromEvent(event *Event) {
|
||||
info.Environment = event.Environment
|
||||
info.Platform = event.Platform
|
||||
info.Release = event.Release
|
||||
info.Dist = event.Dist
|
||||
info.Transaction.ID = event.EventID
|
||||
|
||||
getStringFromContext := func(context map[string]interface{}, originalValue, key string) string {
|
||||
v, ok := context[key]
|
||||
if !ok {
|
||||
return originalValue
|
||||
}
|
||||
|
||||
if s, ok := v.(string); ok {
|
||||
return s
|
||||
}
|
||||
|
||||
return originalValue
|
||||
}
|
||||
|
||||
if runtimeContext, ok := event.Contexts["runtime"]; ok {
|
||||
info.Runtime.Name = getStringFromContext(runtimeContext, info.Runtime.Name, "name")
|
||||
info.Runtime.Version = getStringFromContext(runtimeContext, info.Runtime.Version, "version")
|
||||
}
|
||||
if osContext, ok := event.Contexts["os"]; ok {
|
||||
info.OS.Name = getStringFromContext(osContext, info.OS.Name, "name")
|
||||
}
|
||||
if deviceContext, ok := event.Contexts["device"]; ok {
|
||||
info.Device.Architecture = getStringFromContext(deviceContext, info.Device.Architecture, "arch")
|
||||
}
|
||||
}
|
||||
68
vendor/github.com/getsentry/sentry-go/tracing.go
generated
vendored
68
vendor/github.com/getsentry/sentry-go/tracing.go
generated
vendored
@@ -68,8 +68,6 @@ type Span struct { //nolint: maligned // prefer readability over optimal memory
|
||||
recorder *spanRecorder
|
||||
// span context, can only be set on transactions
|
||||
contexts map[string]Context
|
||||
// collectProfile is a function that collects a profile of the current transaction. May be nil.
|
||||
collectProfile transactionProfiler
|
||||
// a Once instance to make sure that Finish() is only called once.
|
||||
finishOnce sync.Once
|
||||
}
|
||||
@@ -195,14 +193,13 @@ func StartSpan(ctx context.Context, operation string, options ...SpanOption) *Sp
|
||||
clientOptions := span.clientOptions()
|
||||
if clientOptions.EnableTracing {
|
||||
hub := hubFromContext(ctx)
|
||||
if !span.IsTransaction() {
|
||||
// Push a new scope to stack for non transaction span
|
||||
hub.PushScope()
|
||||
}
|
||||
hub.Scope().SetSpan(&span)
|
||||
}
|
||||
|
||||
// Start profiling only if it's a sampled root transaction.
|
||||
if span.IsTransaction() && span.Sampled.Bool() {
|
||||
span.sampleTransactionProfile()
|
||||
}
|
||||
|
||||
return &span
|
||||
}
|
||||
|
||||
@@ -355,6 +352,12 @@ func (s *Span) doFinish() {
|
||||
s.EndTime = monotonicTimeSince(s.StartTime)
|
||||
}
|
||||
|
||||
hub := hubFromContext(s.ctx)
|
||||
if !s.IsTransaction() {
|
||||
// Referenced to StartSpan function that pushes current non-transaction span to scope stack
|
||||
defer hub.PopScope()
|
||||
}
|
||||
|
||||
if !s.Sampled.Bool() {
|
||||
return
|
||||
}
|
||||
@@ -363,14 +366,9 @@ func (s *Span) doFinish() {
|
||||
return
|
||||
}
|
||||
|
||||
if s.collectProfile != nil {
|
||||
event.sdkMetaData.transactionProfile = s.collectProfile(s)
|
||||
}
|
||||
|
||||
// TODO(tracing): add breadcrumbs
|
||||
// (see https://github.com/getsentry/sentry-python/blob/f6f3525f8812f609/sentry_sdk/tracing.py#L372)
|
||||
|
||||
hub := hubFromContext(s.ctx)
|
||||
hub.CaptureEvent(event)
|
||||
}
|
||||
|
||||
@@ -554,10 +552,11 @@ func (s *Span) toEvent() *Event {
|
||||
s.dynamicSamplingContext = DynamicSamplingContextFromTransaction(s)
|
||||
}
|
||||
|
||||
contexts := make(map[string]Context, len(s.contexts))
|
||||
contexts := make(map[string]Context, len(s.contexts)+1)
|
||||
for k, v := range s.contexts {
|
||||
contexts[k] = cloneContext(v)
|
||||
}
|
||||
contexts["trace"] = s.traceContext().Map()
|
||||
|
||||
// Make sure that the transaction source is valid
|
||||
transactionSource := s.Source
|
||||
@@ -725,31 +724,32 @@ const (
|
||||
maxSpanStatus
|
||||
)
|
||||
|
||||
var spanStatuses = [maxSpanStatus]string{
|
||||
"",
|
||||
"ok",
|
||||
"cancelled", // [sic]
|
||||
"unknown",
|
||||
"invalid_argument",
|
||||
"deadline_exceeded",
|
||||
"not_found",
|
||||
"already_exists",
|
||||
"permission_denied",
|
||||
"resource_exhausted",
|
||||
"failed_precondition",
|
||||
"aborted",
|
||||
"out_of_range",
|
||||
"unimplemented",
|
||||
"internal_error",
|
||||
"unavailable",
|
||||
"data_loss",
|
||||
"unauthenticated",
|
||||
}
|
||||
|
||||
func (ss SpanStatus) String() string {
|
||||
if ss >= maxSpanStatus {
|
||||
return ""
|
||||
}
|
||||
m := [maxSpanStatus]string{
|
||||
"",
|
||||
"ok",
|
||||
"cancelled", // [sic]
|
||||
"unknown",
|
||||
"invalid_argument",
|
||||
"deadline_exceeded",
|
||||
"not_found",
|
||||
"already_exists",
|
||||
"permission_denied",
|
||||
"resource_exhausted",
|
||||
"failed_precondition",
|
||||
"aborted",
|
||||
"out_of_range",
|
||||
"unimplemented",
|
||||
"internal_error",
|
||||
"unavailable",
|
||||
"data_loss",
|
||||
"unauthenticated",
|
||||
}
|
||||
return m[ss]
|
||||
return spanStatuses[ss]
|
||||
}
|
||||
|
||||
func (ss SpanStatus) MarshalJSON() ([]byte, error) {
|
||||
|
||||
146
vendor/github.com/getsentry/sentry-go/transport.go
generated
vendored
146
vendor/github.com/getsentry/sentry-go/transport.go
generated
vendored
@@ -35,6 +35,7 @@ type Transport interface {
|
||||
Flush(timeout time.Duration) bool
|
||||
Configure(options ClientOptions)
|
||||
SendEvent(event *Event)
|
||||
Close()
|
||||
}
|
||||
|
||||
func getProxyConfig(options ClientOptions) func(*http.Request) (*url.URL, error) {
|
||||
@@ -95,55 +96,6 @@ func getRequestBodyFromEvent(event *Event) []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func marshalMetrics(metrics []Metric) []byte {
|
||||
var b bytes.Buffer
|
||||
for i, metric := range metrics {
|
||||
b.WriteString(metric.GetKey())
|
||||
if unit := metric.GetUnit(); unit != "" {
|
||||
b.WriteString(fmt.Sprintf("@%s", unit))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("%s|%s", metric.SerializeValue(), metric.GetType()))
|
||||
if serializedTags := metric.SerializeTags(); serializedTags != "" {
|
||||
b.WriteString(fmt.Sprintf("|#%s", serializedTags))
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("|T%d", metric.GetTimestamp()))
|
||||
|
||||
if i < len(metrics)-1 {
|
||||
b.WriteString("\n")
|
||||
}
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func encodeMetric(enc *json.Encoder, b io.Writer, metrics []Metric) error {
|
||||
body := marshalMetrics(metrics)
|
||||
// Item header
|
||||
err := enc.Encode(struct {
|
||||
Type string `json:"type"`
|
||||
Length int `json:"length"`
|
||||
}{
|
||||
Type: metricType,
|
||||
Length: len(body),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// metric payload
|
||||
if _, err = b.Write(body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// "Envelopes should be terminated with a trailing newline."
|
||||
//
|
||||
// [1]: https://develop.sentry.dev/sdk/envelopes/#envelopes
|
||||
if _, err := b.Write([]byte("\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeAttachment(enc *json.Encoder, b io.Writer, attachment *Attachment) error {
|
||||
// Attachment header
|
||||
err := enc.Encode(struct {
|
||||
@@ -228,8 +180,6 @@ func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMes
|
||||
switch event.Type {
|
||||
case transactionType, checkInType:
|
||||
err = encodeEnvelopeItem(enc, event.Type, body)
|
||||
case metricType:
|
||||
err = encodeMetric(enc, &b, event.Metrics)
|
||||
default:
|
||||
err = encodeEnvelopeItem(enc, eventType, body)
|
||||
}
|
||||
@@ -245,18 +195,6 @@ func envelopeFromBody(event *Event, dsn *Dsn, sentAt time.Time, body json.RawMes
|
||||
}
|
||||
}
|
||||
|
||||
// Profile data
|
||||
if event.sdkMetaData.transactionProfile != nil {
|
||||
body, err = json.Marshal(event.sdkMetaData.transactionProfile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = encodeEnvelopeItem(enc, profileType, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
@@ -279,10 +217,12 @@ func getRequestFromEvent(ctx context.Context, event *Event, dsn *Dsn) (r *http.R
|
||||
r.Header.Set("X-Sentry-Auth", auth)
|
||||
}
|
||||
}()
|
||||
|
||||
body := getRequestBodyFromEvent(event)
|
||||
if body == nil {
|
||||
return nil, errors.New("event could not be marshaled")
|
||||
}
|
||||
|
||||
envelope, err := envelopeFromBody(event, dsn, time.Now(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -350,6 +290,9 @@ type HTTPTransport struct {
|
||||
|
||||
mu sync.RWMutex
|
||||
limits ratelimit.Map
|
||||
|
||||
// receiving signal will terminate worker.
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
// NewHTTPTransport returns a new pre-configured instance of HTTPTransport.
|
||||
@@ -357,6 +300,7 @@ func NewHTTPTransport() *HTTPTransport {
|
||||
transport := HTTPTransport{
|
||||
BufferSize: defaultBufferSize,
|
||||
Timeout: defaultTimeout,
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
return &transport
|
||||
}
|
||||
@@ -522,6 +466,15 @@ fail:
|
||||
return false
|
||||
}
|
||||
|
||||
// Close will terminate events sending loop.
|
||||
// It useful to prevent goroutines leak in case of multiple HTTPTransport instances initiated.
|
||||
//
|
||||
// Close should be called after Flush and before terminating the program
|
||||
// otherwise some events may be lost.
|
||||
func (t *HTTPTransport) Close() {
|
||||
close(t.done)
|
||||
}
|
||||
|
||||
func (t *HTTPTransport) worker() {
|
||||
for b := range t.buffer {
|
||||
// Signal that processing of the current batch has started.
|
||||
@@ -532,35 +485,44 @@ func (t *HTTPTransport) worker() {
|
||||
t.buffer <- b
|
||||
|
||||
// Process all batch items.
|
||||
for item := range b.items {
|
||||
if t.disabled(item.category) {
|
||||
continue
|
||||
}
|
||||
|
||||
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 >= 400 && response.StatusCode <= 599 {
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
Logger.Printf("Error while reading response code: %v", err)
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-t.done:
|
||||
return
|
||||
case item, open := <-b.items:
|
||||
if !open {
|
||||
break loop
|
||||
}
|
||||
if t.disabled(item.category) {
|
||||
continue
|
||||
}
|
||||
Logger.Printf("Sending %s failed with the following error: %s", eventType, string(b))
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
if t.limits == nil {
|
||||
t.limits = make(ratelimit.Map)
|
||||
}
|
||||
t.limits.Merge(ratelimit.FromResponse(response))
|
||||
t.mu.Unlock()
|
||||
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 >= 400 && response.StatusCode <= 599 {
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
Logger.Printf("Error while reading response code: %v", err)
|
||||
}
|
||||
Logger.Printf("Sending %s failed with the following error: %s", eventType, string(b))
|
||||
}
|
||||
|
||||
// Drain body up to a limit and close it, allowing the
|
||||
// transport to reuse TCP connections.
|
||||
_, _ = io.CopyN(io.Discard, response.Body, maxDrainResponseBytes)
|
||||
response.Body.Close()
|
||||
t.mu.Lock()
|
||||
if t.limits == nil {
|
||||
t.limits = make(ratelimit.Map)
|
||||
}
|
||||
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(io.Discard, response.Body, maxDrainResponseBytes)
|
||||
response.Body.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Signal that processing of the batch is done.
|
||||
@@ -648,6 +610,8 @@ func (t *HTTPSyncTransport) SendEvent(event *Event) {
|
||||
t.SendEventWithContext(context.Background(), event)
|
||||
}
|
||||
|
||||
func (t *HTTPSyncTransport) Close() {}
|
||||
|
||||
// SendEventWithContext assembles a new packet out of Event and sends it to the remote server.
|
||||
func (t *HTTPSyncTransport) SendEventWithContext(ctx context.Context, event *Event) {
|
||||
if t.dsn == nil {
|
||||
@@ -667,8 +631,6 @@ func (t *HTTPSyncTransport) SendEventWithContext(ctx context.Context, event *Eve
|
||||
switch {
|
||||
case event.Type == transactionType:
|
||||
eventType = "transaction"
|
||||
case event.Type == metricType:
|
||||
eventType = metricType
|
||||
default:
|
||||
eventType = fmt.Sprintf("%s event", event.Level)
|
||||
}
|
||||
@@ -743,3 +705,5 @@ func (noopTransport) SendEvent(*Event) {
|
||||
func (noopTransport) Flush(time.Duration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (noopTransport) Close() {}
|
||||
|
||||
6
vendor/github.com/klauspost/compress/.goreleaser.yml
generated
vendored
6
vendor/github.com/klauspost/compress/.goreleaser.yml
generated
vendored
@@ -1,5 +1,5 @@
|
||||
# This is an example goreleaser.yaml file with some sane defaults.
|
||||
# Make sure to check the documentation at http://goreleaser.com
|
||||
version: 2
|
||||
|
||||
before:
|
||||
hooks:
|
||||
- ./gen.sh
|
||||
@@ -99,7 +99,7 @@ archives:
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ .Tag }}-next"
|
||||
version_template: "{{ .Tag }}-next"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
|
||||
29
vendor/github.com/klauspost/compress/README.md
generated
vendored
29
vendor/github.com/klauspost/compress/README.md
generated
vendored
@@ -16,6 +16,27 @@ This package provides various compression algorithms.
|
||||
|
||||
# changelog
|
||||
|
||||
* Sep 23rd, 2024 - [1.17.10](https://github.com/klauspost/compress/releases/tag/v1.17.10)
|
||||
* gzhttp: Add TransportAlwaysDecompress option. https://github.com/klauspost/compress/pull/978
|
||||
* gzhttp: Add supported decompress request body by @mirecl in https://github.com/klauspost/compress/pull/1002
|
||||
* s2: Add EncodeBuffer buffer recycling callback https://github.com/klauspost/compress/pull/982
|
||||
* zstd: Improve memory usage on small streaming encodes https://github.com/klauspost/compress/pull/1007
|
||||
* flate: read data written with partial flush by @vajexal in https://github.com/klauspost/compress/pull/996
|
||||
|
||||
* Jun 12th, 2024 - [1.17.9](https://github.com/klauspost/compress/releases/tag/v1.17.9)
|
||||
* s2: Reduce ReadFrom temporary allocations https://github.com/klauspost/compress/pull/949
|
||||
* flate, zstd: Shave some bytes off amd64 matchLen by @greatroar in https://github.com/klauspost/compress/pull/963
|
||||
* Upgrade zip/zlib to 1.22.4 upstream https://github.com/klauspost/compress/pull/970 https://github.com/klauspost/compress/pull/971
|
||||
* zstd: BuildDict fails with RLE table https://github.com/klauspost/compress/pull/951
|
||||
|
||||
* Apr 9th, 2024 - [1.17.8](https://github.com/klauspost/compress/releases/tag/v1.17.8)
|
||||
* zstd: Reject blocks where reserved values are not 0 https://github.com/klauspost/compress/pull/885
|
||||
* zstd: Add RLE detection+encoding https://github.com/klauspost/compress/pull/938
|
||||
|
||||
* Feb 21st, 2024 - [1.17.7](https://github.com/klauspost/compress/releases/tag/v1.17.7)
|
||||
* s2: Add AsyncFlush method: Complete the block without flushing by @Jille in https://github.com/klauspost/compress/pull/927
|
||||
* s2: Fix literal+repeat exceeds dst crash https://github.com/klauspost/compress/pull/930
|
||||
|
||||
* Feb 5th, 2024 - [1.17.6](https://github.com/klauspost/compress/releases/tag/v1.17.6)
|
||||
* zstd: Fix incorrect repeat coding in best mode https://github.com/klauspost/compress/pull/923
|
||||
* s2: Fix DecodeConcurrent deadlock on errors https://github.com/klauspost/compress/pull/925
|
||||
@@ -81,7 +102,7 @@ https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/comp
|
||||
* zstd: Various minor improvements by @greatroar in https://github.com/klauspost/compress/pull/788 https://github.com/klauspost/compress/pull/794 https://github.com/klauspost/compress/pull/795
|
||||
* s2: Fix huge block overflow https://github.com/klauspost/compress/pull/779
|
||||
* s2: Allow CustomEncoder fallback https://github.com/klauspost/compress/pull/780
|
||||
* gzhttp: Suppport ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799
|
||||
* gzhttp: Support ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799
|
||||
|
||||
* Mar 13, 2023 - [v1.16.1](https://github.com/klauspost/compress/releases/tag/v1.16.1)
|
||||
* zstd: Speed up + improve best encoder by @greatroar in https://github.com/klauspost/compress/pull/776
|
||||
@@ -136,7 +157,7 @@ https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/comp
|
||||
* zstd: Add [WithDecodeAllCapLimit](https://pkg.go.dev/github.com/klauspost/compress@v1.15.10/zstd#WithDecodeAllCapLimit) https://github.com/klauspost/compress/pull/649
|
||||
* Add Go 1.19 - deprecate Go 1.16 https://github.com/klauspost/compress/pull/651
|
||||
* flate: Improve level 5+6 compression https://github.com/klauspost/compress/pull/656
|
||||
* zstd: Improve "better" compresssion https://github.com/klauspost/compress/pull/657
|
||||
* zstd: Improve "better" compression https://github.com/klauspost/compress/pull/657
|
||||
* s2: Improve "best" compression https://github.com/klauspost/compress/pull/658
|
||||
* s2: Improve "better" compression. https://github.com/klauspost/compress/pull/635
|
||||
* s2: Slightly faster non-assembly decompression https://github.com/klauspost/compress/pull/646
|
||||
@@ -339,7 +360,7 @@ While the release has been extensively tested, it is recommended to testing when
|
||||
* s2: Fix binaries.
|
||||
|
||||
* Feb 25, 2021 (v1.11.8)
|
||||
* s2: Fixed occational out-of-bounds write on amd64. Upgrade recommended.
|
||||
* s2: Fixed occasional out-of-bounds write on amd64. Upgrade recommended.
|
||||
* s2: Add AMD64 assembly for better mode. 25-50% faster. [#315](https://github.com/klauspost/compress/pull/315)
|
||||
* s2: Less upfront decoder allocation. [#322](https://github.com/klauspost/compress/pull/322)
|
||||
* zstd: Faster "compression" of incompressible data. [#314](https://github.com/klauspost/compress/pull/314)
|
||||
@@ -518,7 +539,7 @@ While the release has been extensively tested, it is recommended to testing when
|
||||
* Feb 19, 2016: Faster bit writer, level -2 is 15% faster, level 1 is 4% faster.
|
||||
* Feb 19, 2016: Handle small payloads faster in level 1-3.
|
||||
* Feb 19, 2016: Added faster level 2 + 3 compression modes.
|
||||
* Feb 19, 2016: [Rebalanced compression levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/), so there is a more even progresssion in terms of compression. New default level is 5.
|
||||
* Feb 19, 2016: [Rebalanced compression levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/), so there is a more even progression in terms of compression. New default level is 5.
|
||||
* Feb 14, 2016: Snappy: Merge upstream changes.
|
||||
* Feb 14, 2016: Snappy: Fix aggressive skipping.
|
||||
* Feb 14, 2016: Snappy: Update benchmark.
|
||||
|
||||
2
vendor/github.com/klauspost/compress/fse/decompress.go
generated
vendored
2
vendor/github.com/klauspost/compress/fse/decompress.go
generated
vendored
@@ -15,7 +15,7 @@ const (
|
||||
// It is possible, but by no way guaranteed that corrupt data will
|
||||
// return an error.
|
||||
// It is up to the caller to verify integrity of the returned data.
|
||||
// Use a predefined Scrach to set maximum acceptable output size.
|
||||
// Use a predefined Scratch to set maximum acceptable output size.
|
||||
func Decompress(b []byte, s *Scratch) ([]byte, error) {
|
||||
s, err := s.prepare(b)
|
||||
if err != nil {
|
||||
|
||||
4
vendor/github.com/klauspost/compress/huff0/decompress.go
generated
vendored
4
vendor/github.com/klauspost/compress/huff0/decompress.go
generated
vendored
@@ -1136,7 +1136,7 @@ func (s *Scratch) matches(ct cTable, w io.Writer) {
|
||||
errs++
|
||||
}
|
||||
if errs > 0 {
|
||||
fmt.Fprintf(w, "%d errros in base, stopping\n", errs)
|
||||
fmt.Fprintf(w, "%d errors in base, stopping\n", errs)
|
||||
continue
|
||||
}
|
||||
// Ensure that all combinations are covered.
|
||||
@@ -1152,7 +1152,7 @@ func (s *Scratch) matches(ct cTable, w io.Writer) {
|
||||
errs++
|
||||
}
|
||||
if errs > 20 {
|
||||
fmt.Fprintf(w, "%d errros, stopping\n", errs)
|
||||
fmt.Fprintf(w, "%d errors, stopping\n", errs)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/github.com/klauspost/compress/zstd/blockdec.go
generated
vendored
4
vendor/github.com/klauspost/compress/zstd/blockdec.go
generated
vendored
@@ -598,7 +598,9 @@ func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) {
|
||||
printf("RLE set to 0x%x, code: %v", symb, v)
|
||||
}
|
||||
case compModeFSE:
|
||||
println("Reading table for", tableIndex(i))
|
||||
if debugDecoder {
|
||||
println("Reading table for", tableIndex(i))
|
||||
}
|
||||
if seq.fse == nil || seq.fse.preDefined {
|
||||
seq.fse = fseDecoderPool.Get().(*fseDecoder)
|
||||
}
|
||||
|
||||
32
vendor/github.com/klauspost/compress/zstd/enc_better.go
generated
vendored
32
vendor/github.com/klauspost/compress/zstd/enc_better.go
generated
vendored
@@ -179,9 +179,9 @@ encodeLoop:
|
||||
if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) {
|
||||
// Consider history as well.
|
||||
var seq seq
|
||||
lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
length := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
|
||||
seq.matchLen = uint32(lenght - zstdMinMatch)
|
||||
seq.matchLen = uint32(length - zstdMinMatch)
|
||||
|
||||
// We might be able to match backwards.
|
||||
// Extend as long as we can.
|
||||
@@ -210,12 +210,12 @@ encodeLoop:
|
||||
|
||||
// Index match start+1 (long) -> s - 1
|
||||
index0 := s + repOff
|
||||
s += lenght + repOff
|
||||
s += length + repOff
|
||||
|
||||
nextEmit = s
|
||||
if s >= sLimit {
|
||||
if debugEncoder {
|
||||
println("repeat ended", s, lenght)
|
||||
println("repeat ended", s, length)
|
||||
|
||||
}
|
||||
break encodeLoop
|
||||
@@ -241,9 +241,9 @@ encodeLoop:
|
||||
if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) {
|
||||
// Consider history as well.
|
||||
var seq seq
|
||||
lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src)
|
||||
length := 8 + e.matchlen(s+8+repOff2, repIndex+8, src)
|
||||
|
||||
seq.matchLen = uint32(lenght - zstdMinMatch)
|
||||
seq.matchLen = uint32(length - zstdMinMatch)
|
||||
|
||||
// We might be able to match backwards.
|
||||
// Extend as long as we can.
|
||||
@@ -270,11 +270,11 @@ encodeLoop:
|
||||
}
|
||||
blk.sequences = append(blk.sequences, seq)
|
||||
|
||||
s += lenght + repOff2
|
||||
s += length + repOff2
|
||||
nextEmit = s
|
||||
if s >= sLimit {
|
||||
if debugEncoder {
|
||||
println("repeat ended", s, lenght)
|
||||
println("repeat ended", s, length)
|
||||
|
||||
}
|
||||
break encodeLoop
|
||||
@@ -708,9 +708,9 @@ encodeLoop:
|
||||
if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) {
|
||||
// Consider history as well.
|
||||
var seq seq
|
||||
lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
length := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
|
||||
seq.matchLen = uint32(lenght - zstdMinMatch)
|
||||
seq.matchLen = uint32(length - zstdMinMatch)
|
||||
|
||||
// We might be able to match backwards.
|
||||
// Extend as long as we can.
|
||||
@@ -738,12 +738,12 @@ encodeLoop:
|
||||
blk.sequences = append(blk.sequences, seq)
|
||||
|
||||
// Index match start+1 (long) -> s - 1
|
||||
s += lenght + repOff
|
||||
s += length + repOff
|
||||
|
||||
nextEmit = s
|
||||
if s >= sLimit {
|
||||
if debugEncoder {
|
||||
println("repeat ended", s, lenght)
|
||||
println("repeat ended", s, length)
|
||||
|
||||
}
|
||||
break encodeLoop
|
||||
@@ -772,9 +772,9 @@ encodeLoop:
|
||||
if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) {
|
||||
// Consider history as well.
|
||||
var seq seq
|
||||
lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src)
|
||||
length := 8 + e.matchlen(s+8+repOff2, repIndex+8, src)
|
||||
|
||||
seq.matchLen = uint32(lenght - zstdMinMatch)
|
||||
seq.matchLen = uint32(length - zstdMinMatch)
|
||||
|
||||
// We might be able to match backwards.
|
||||
// Extend as long as we can.
|
||||
@@ -801,11 +801,11 @@ encodeLoop:
|
||||
}
|
||||
blk.sequences = append(blk.sequences, seq)
|
||||
|
||||
s += lenght + repOff2
|
||||
s += length + repOff2
|
||||
nextEmit = s
|
||||
if s >= sLimit {
|
||||
if debugEncoder {
|
||||
println("repeat ended", s, lenght)
|
||||
println("repeat ended", s, length)
|
||||
|
||||
}
|
||||
break encodeLoop
|
||||
|
||||
16
vendor/github.com/klauspost/compress/zstd/enc_dfast.go
generated
vendored
16
vendor/github.com/klauspost/compress/zstd/enc_dfast.go
generated
vendored
@@ -138,9 +138,9 @@ encodeLoop:
|
||||
if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) {
|
||||
// Consider history as well.
|
||||
var seq seq
|
||||
lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
length := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
|
||||
seq.matchLen = uint32(lenght - zstdMinMatch)
|
||||
seq.matchLen = uint32(length - zstdMinMatch)
|
||||
|
||||
// We might be able to match backwards.
|
||||
// Extend as long as we can.
|
||||
@@ -166,11 +166,11 @@ encodeLoop:
|
||||
println("repeat sequence", seq, "next s:", s)
|
||||
}
|
||||
blk.sequences = append(blk.sequences, seq)
|
||||
s += lenght + repOff
|
||||
s += length + repOff
|
||||
nextEmit = s
|
||||
if s >= sLimit {
|
||||
if debugEncoder {
|
||||
println("repeat ended", s, lenght)
|
||||
println("repeat ended", s, length)
|
||||
|
||||
}
|
||||
break encodeLoop
|
||||
@@ -798,9 +798,9 @@ encodeLoop:
|
||||
if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) {
|
||||
// Consider history as well.
|
||||
var seq seq
|
||||
lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
length := 4 + e.matchlen(s+4+repOff, repIndex+4, src)
|
||||
|
||||
seq.matchLen = uint32(lenght - zstdMinMatch)
|
||||
seq.matchLen = uint32(length - zstdMinMatch)
|
||||
|
||||
// We might be able to match backwards.
|
||||
// Extend as long as we can.
|
||||
@@ -826,11 +826,11 @@ encodeLoop:
|
||||
println("repeat sequence", seq, "next s:", s)
|
||||
}
|
||||
blk.sequences = append(blk.sequences, seq)
|
||||
s += lenght + repOff
|
||||
s += length + repOff
|
||||
nextEmit = s
|
||||
if s >= sLimit {
|
||||
if debugEncoder {
|
||||
println("repeat ended", s, lenght)
|
||||
println("repeat ended", s, length)
|
||||
|
||||
}
|
||||
break encodeLoop
|
||||
|
||||
45
vendor/github.com/klauspost/compress/zstd/encoder.go
generated
vendored
45
vendor/github.com/klauspost/compress/zstd/encoder.go
generated
vendored
@@ -6,6 +6,7 @@ package zstd
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
@@ -149,6 +150,9 @@ func (e *Encoder) ResetContentSize(w io.Writer, size int64) {
|
||||
// and write CRC if requested.
|
||||
func (e *Encoder) Write(p []byte) (n int, err error) {
|
||||
s := &e.state
|
||||
if s.eofWritten {
|
||||
return 0, ErrEncoderClosed
|
||||
}
|
||||
for len(p) > 0 {
|
||||
if len(p)+len(s.filling) < e.o.blockSize {
|
||||
if e.o.crc {
|
||||
@@ -202,7 +206,7 @@ func (e *Encoder) nextBlock(final bool) error {
|
||||
return nil
|
||||
}
|
||||
if final && len(s.filling) > 0 {
|
||||
s.current = e.EncodeAll(s.filling, s.current[:0])
|
||||
s.current = e.encodeAll(s.encoder, s.filling, s.current[:0])
|
||||
var n2 int
|
||||
n2, s.err = s.w.Write(s.current)
|
||||
if s.err != nil {
|
||||
@@ -288,6 +292,9 @@ func (e *Encoder) nextBlock(final bool) error {
|
||||
s.filling, s.current, s.previous = s.previous[:0], s.filling, s.current
|
||||
s.nInput += int64(len(s.current))
|
||||
s.wg.Add(1)
|
||||
if final {
|
||||
s.eofWritten = true
|
||||
}
|
||||
go func(src []byte) {
|
||||
if debugEncoder {
|
||||
println("Adding block,", len(src), "bytes, final:", final)
|
||||
@@ -303,9 +310,6 @@ func (e *Encoder) nextBlock(final bool) error {
|
||||
blk := enc.Block()
|
||||
enc.Encode(blk, src)
|
||||
blk.last = final
|
||||
if final {
|
||||
s.eofWritten = true
|
||||
}
|
||||
// Wait for pending writes.
|
||||
s.wWg.Wait()
|
||||
if s.writeErr != nil {
|
||||
@@ -401,12 +405,20 @@ func (e *Encoder) Flush() error {
|
||||
if len(s.filling) > 0 {
|
||||
err := e.nextBlock(false)
|
||||
if err != nil {
|
||||
// Ignore Flush after Close.
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
s.wg.Wait()
|
||||
s.wWg.Wait()
|
||||
if s.err != nil {
|
||||
// Ignore Flush after Close.
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
return nil
|
||||
}
|
||||
return s.err
|
||||
}
|
||||
return s.writeErr
|
||||
@@ -422,6 +434,9 @@ func (e *Encoder) Close() error {
|
||||
}
|
||||
err := e.nextBlock(true)
|
||||
if err != nil {
|
||||
if errors.Is(s.err, ErrEncoderClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if s.frameContentSize > 0 {
|
||||
@@ -459,6 +474,11 @@ func (e *Encoder) Close() error {
|
||||
}
|
||||
_, s.err = s.w.Write(frame)
|
||||
}
|
||||
if s.err == nil {
|
||||
s.err = ErrEncoderClosed
|
||||
return nil
|
||||
}
|
||||
|
||||
return s.err
|
||||
}
|
||||
|
||||
@@ -469,6 +489,15 @@ func (e *Encoder) Close() error {
|
||||
// Data compressed with EncodeAll can be decoded with the Decoder,
|
||||
// using either a stream or DecodeAll.
|
||||
func (e *Encoder) EncodeAll(src, dst []byte) []byte {
|
||||
e.init.Do(e.initialize)
|
||||
enc := <-e.encoders
|
||||
defer func() {
|
||||
e.encoders <- enc
|
||||
}()
|
||||
return e.encodeAll(enc, src, dst)
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeAll(enc encoder, src, dst []byte) []byte {
|
||||
if len(src) == 0 {
|
||||
if e.o.fullZero {
|
||||
// Add frame header.
|
||||
@@ -491,13 +520,7 @@ func (e *Encoder) EncodeAll(src, dst []byte) []byte {
|
||||
}
|
||||
return dst
|
||||
}
|
||||
e.init.Do(e.initialize)
|
||||
enc := <-e.encoders
|
||||
defer func() {
|
||||
// Release encoder reference to last block.
|
||||
// If a non-single block is needed the encoder will reset again.
|
||||
e.encoders <- enc
|
||||
}()
|
||||
|
||||
// Use single segments when above minimum window and below window size.
|
||||
single := len(src) <= e.o.windowSize && len(src) > MinWindowSize
|
||||
if e.o.single != nil {
|
||||
|
||||
4
vendor/github.com/klauspost/compress/zstd/framedec.go
generated
vendored
4
vendor/github.com/klauspost/compress/zstd/framedec.go
generated
vendored
@@ -146,7 +146,9 @@ func (d *frameDec) reset(br byteBuffer) error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3)
|
||||
if debugDecoder {
|
||||
printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3)
|
||||
}
|
||||
windowLog := 10 + (wd >> 3)
|
||||
windowBase := uint64(1) << windowLog
|
||||
windowAdd := (windowBase / 8) * uint64(wd&0x7)
|
||||
|
||||
4
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go
generated
vendored
4
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go
generated
vendored
@@ -146,7 +146,7 @@ func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) {
|
||||
return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
||||
|
||||
default:
|
||||
return true, fmt.Errorf("sequenceDecs_decode returned erronous code %d", errCode)
|
||||
return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode)
|
||||
}
|
||||
|
||||
s.seqSize += ctx.litRemain
|
||||
@@ -292,7 +292,7 @@ func (s *sequenceDecs) decode(seqs []seqVals) error {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
return fmt.Errorf("sequenceDecs_decode_amd64 returned erronous code %d", errCode)
|
||||
return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode)
|
||||
}
|
||||
|
||||
if ctx.litRemain < 0 {
|
||||
|
||||
8
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s
generated
vendored
8
vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s
generated
vendored
@@ -1814,7 +1814,7 @@ TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32
|
||||
MOVQ 40(SP), AX
|
||||
ADDQ AX, 48(SP)
|
||||
|
||||
// Calculate poiter to s.out[cap(s.out)] (a past-end pointer)
|
||||
// Calculate pointer to s.out[cap(s.out)] (a past-end pointer)
|
||||
ADDQ R10, 32(SP)
|
||||
|
||||
// outBase += outPosition
|
||||
@@ -2376,7 +2376,7 @@ TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32
|
||||
MOVQ 40(SP), CX
|
||||
ADDQ CX, 48(SP)
|
||||
|
||||
// Calculate poiter to s.out[cap(s.out)] (a past-end pointer)
|
||||
// Calculate pointer to s.out[cap(s.out)] (a past-end pointer)
|
||||
ADDQ R9, 32(SP)
|
||||
|
||||
// outBase += outPosition
|
||||
@@ -2896,7 +2896,7 @@ TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32
|
||||
MOVQ 40(SP), AX
|
||||
ADDQ AX, 48(SP)
|
||||
|
||||
// Calculate poiter to s.out[cap(s.out)] (a past-end pointer)
|
||||
// Calculate pointer to s.out[cap(s.out)] (a past-end pointer)
|
||||
ADDQ R10, 32(SP)
|
||||
|
||||
// outBase += outPosition
|
||||
@@ -3560,7 +3560,7 @@ TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32
|
||||
MOVQ 40(SP), CX
|
||||
ADDQ CX, 48(SP)
|
||||
|
||||
// Calculate poiter to s.out[cap(s.out)] (a past-end pointer)
|
||||
// Calculate pointer to s.out[cap(s.out)] (a past-end pointer)
|
||||
ADDQ R9, 32(SP)
|
||||
|
||||
// outBase += outPosition
|
||||
|
||||
4
vendor/github.com/klauspost/compress/zstd/zstd.go
generated
vendored
4
vendor/github.com/klauspost/compress/zstd/zstd.go
generated
vendored
@@ -88,6 +88,10 @@ var (
|
||||
// Close has been called.
|
||||
ErrDecoderClosed = errors.New("decoder used after Close")
|
||||
|
||||
// ErrEncoderClosed will be returned if the Encoder was used after
|
||||
// Close has been called.
|
||||
ErrEncoderClosed = errors.New("encoder used after Close")
|
||||
|
||||
// ErrDecoderNilInput is returned when a nil Reader was provided
|
||||
// and an operation other than Reset/DecodeAll/Close was attempted.
|
||||
ErrDecoderNilInput = errors.New("nil input provided as reader")
|
||||
|
||||
4
vendor/github.com/prometheus/common/expfmt/encode.go
generated
vendored
4
vendor/github.com/prometheus/common/expfmt/encode.go
generated
vendored
@@ -68,7 +68,7 @@ func Negotiate(h http.Header) Format {
|
||||
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
|
||||
switch Format(escapeParam) {
|
||||
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
|
||||
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
|
||||
escapingScheme = Format("; escaping=" + escapeParam)
|
||||
default:
|
||||
// If the escaping parameter is unknown, ignore it.
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
|
||||
if escapeParam := ac.Params[model.EscapingKey]; escapeParam != "" {
|
||||
switch Format(escapeParam) {
|
||||
case model.AllowUTF8, model.EscapeUnderscores, model.EscapeDots, model.EscapeValues:
|
||||
escapingScheme = Format(fmt.Sprintf("; escaping=%s", escapeParam))
|
||||
escapingScheme = Format("; escaping=" + escapeParam)
|
||||
default:
|
||||
// If the escaping parameter is unknown, ignore it.
|
||||
}
|
||||
|
||||
4
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
4
vendor/github.com/prometheus/common/expfmt/expfmt.go
generated
vendored
@@ -15,7 +15,7 @@
|
||||
package expfmt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/common/model"
|
||||
@@ -109,7 +109,7 @@ func NewOpenMetricsFormat(version string) (Format, error) {
|
||||
if version == OpenMetricsVersion_1_0_0 {
|
||||
return FmtOpenMetrics_1_0_0, nil
|
||||
}
|
||||
return FmtUnknown, fmt.Errorf("unknown open metrics version string")
|
||||
return FmtUnknown, errors.New("unknown open metrics version string")
|
||||
}
|
||||
|
||||
// WithEscapingScheme returns a copy of Format with the specified escaping
|
||||
|
||||
8
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
8
vendor/github.com/prometheus/common/expfmt/openmetrics_create.go
generated
vendored
@@ -38,7 +38,7 @@ type EncoderOption func(*encoderOption)
|
||||
|
||||
// WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder
|
||||
// to include _created lines (See
|
||||
// https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1).
|
||||
// https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#counter-1).
|
||||
// Created timestamps can improve the accuracy of series reset detection, but
|
||||
// come with a bandwidth cost.
|
||||
//
|
||||
@@ -102,7 +102,7 @@ func WithUnit() EncoderOption {
|
||||
//
|
||||
// - According to the OM specs, the `# UNIT` line is optional, but if populated,
|
||||
// the unit has to be present in the metric name as its suffix:
|
||||
// (see https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#unit).
|
||||
// (see https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#unit).
|
||||
// However, in order to accommodate any potential scenario where such a change in the
|
||||
// metric name is not desirable, the users are here given the choice of either explicitly
|
||||
// opt in, in case they wish for the unit to be included in the output AND in the metric name
|
||||
@@ -152,8 +152,8 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...E
|
||||
if metricType == dto.MetricType_COUNTER && strings.HasSuffix(compliantName, "_total") {
|
||||
compliantName = name[:len(name)-6]
|
||||
}
|
||||
if toOM.withUnit && in.Unit != nil && !strings.HasSuffix(compliantName, fmt.Sprintf("_%s", *in.Unit)) {
|
||||
compliantName = compliantName + fmt.Sprintf("_%s", *in.Unit)
|
||||
if toOM.withUnit && in.Unit != nil && !strings.HasSuffix(compliantName, "_"+*in.Unit) {
|
||||
compliantName = compliantName + "_" + *in.Unit
|
||||
}
|
||||
|
||||
// Comments, first HELP, then TYPE.
|
||||
|
||||
2
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
2
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
@@ -895,7 +895,7 @@ func histogramMetricName(name string) string {
|
||||
|
||||
func parseFloat(s string) (float64, error) {
|
||||
if strings.ContainsAny(s, "pP_") {
|
||||
return 0, fmt.Errorf("unsupported character in float")
|
||||
return 0, errors.New("unsupported character in float")
|
||||
}
|
||||
return strconv.ParseFloat(s, 64)
|
||||
}
|
||||
|
||||
7
vendor/github.com/prometheus/common/model/alert.go
generated
vendored
7
vendor/github.com/prometheus/common/model/alert.go
generated
vendored
@@ -14,6 +14,7 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
@@ -89,16 +90,16 @@ func (a *Alert) StatusAt(ts time.Time) AlertStatus {
|
||||
// Validate checks whether the alert data is inconsistent.
|
||||
func (a *Alert) Validate() error {
|
||||
if a.StartsAt.IsZero() {
|
||||
return fmt.Errorf("start time missing")
|
||||
return errors.New("start time missing")
|
||||
}
|
||||
if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) {
|
||||
return fmt.Errorf("start time must be before end time")
|
||||
return errors.New("start time must be before end time")
|
||||
}
|
||||
if err := a.Labels.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid label set: %w", err)
|
||||
}
|
||||
if len(a.Labels) == 0 {
|
||||
return fmt.Errorf("at least one label pair required")
|
||||
return errors.New("at least one label pair required")
|
||||
}
|
||||
if err := a.Annotations.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid annotations: %w", err)
|
||||
|
||||
2
vendor/github.com/prometheus/common/model/labelset_string.go
generated
vendored
2
vendor/github.com/prometheus/common/model/labelset_string.go
generated
vendored
@@ -11,8 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build go1.21
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
|
||||
39
vendor/github.com/prometheus/common/model/labelset_string_go120.go
generated
vendored
39
vendor/github.com/prometheus/common/model/labelset_string_go120.go
generated
vendored
@@ -1,39 +0,0 @@
|
||||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !go1.21
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// String was optimized using functions not available for go 1.20
|
||||
// or lower. We keep the old implementation for compatibility with client_golang.
|
||||
// Once client golang drops support for go 1.20 (scheduled for August 2024), this
|
||||
// file can be removed.
|
||||
func (l LabelSet) String() string {
|
||||
labelNames := make([]string, 0, len(l))
|
||||
for name := range l {
|
||||
labelNames = append(labelNames, string(name))
|
||||
}
|
||||
sort.Strings(labelNames)
|
||||
lstrs := make([]string, 0, len(l))
|
||||
for _, name := range labelNames {
|
||||
lstrs = append(lstrs, fmt.Sprintf("%s=%q", name, l[LabelName(name)]))
|
||||
}
|
||||
return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
|
||||
}
|
||||
45
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
45
vendor/github.com/prometheus/common/model/metric.go
generated
vendored
@@ -14,9 +14,11 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -26,13 +28,13 @@ import (
|
||||
|
||||
var (
|
||||
// NameValidationScheme determines the method of name validation to be used by
|
||||
// all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8 mode
|
||||
// in isolation from other components that don't support UTF-8 may result in
|
||||
// bugs or other undefined behavior. This value is intended to be set by
|
||||
// UTF-8-aware binaries as part of their startup. To avoid need for locking,
|
||||
// this value should be set once, ideally in an init(), before multiple
|
||||
// goroutines are started.
|
||||
NameValidationScheme = LegacyValidation
|
||||
// all calls to IsValidMetricName() and LabelName IsValid(). Setting UTF-8
|
||||
// mode in isolation from other components that don't support UTF-8 may result
|
||||
// in bugs or other undefined behavior. This value can be set to
|
||||
// LegacyValidation during startup if a binary is not UTF-8-aware binaries. To
|
||||
// avoid need for locking, this value should be set once, ideally in an
|
||||
// init(), before multiple goroutines are started.
|
||||
NameValidationScheme = UTF8Validation
|
||||
|
||||
// NameEscapingScheme defines the default way that names will be escaped when
|
||||
// presented to systems that do not support UTF-8 names. If the Content-Type
|
||||
@@ -269,10 +271,6 @@ func metricNeedsEscaping(m *dto.Metric) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
lowerhex = "0123456789abcdef"
|
||||
)
|
||||
|
||||
// EscapeName escapes the incoming name according to the provided escaping
|
||||
// scheme. Depending on the rules of escaping, this may cause no change in the
|
||||
// string that is returned. (Especially NoEscaping, which by definition is a
|
||||
@@ -307,7 +305,7 @@ func EscapeName(name string, scheme EscapingScheme) string {
|
||||
} else if isValidLegacyRune(b, i) {
|
||||
escaped.WriteRune(b)
|
||||
} else {
|
||||
escaped.WriteRune('_')
|
||||
escaped.WriteString("__")
|
||||
}
|
||||
}
|
||||
return escaped.String()
|
||||
@@ -317,21 +315,15 @@ func EscapeName(name string, scheme EscapingScheme) string {
|
||||
}
|
||||
escaped.WriteString("U__")
|
||||
for i, b := range name {
|
||||
if isValidLegacyRune(b, i) {
|
||||
if b == '_' {
|
||||
escaped.WriteString("__")
|
||||
} else if isValidLegacyRune(b, i) {
|
||||
escaped.WriteRune(b)
|
||||
} else if !utf8.ValidRune(b) {
|
||||
escaped.WriteString("_FFFD_")
|
||||
} else if b < 0x100 {
|
||||
} else {
|
||||
escaped.WriteRune('_')
|
||||
for s := 4; s >= 0; s -= 4 {
|
||||
escaped.WriteByte(lowerhex[b>>uint(s)&0xF])
|
||||
}
|
||||
escaped.WriteRune('_')
|
||||
} else if b < 0x10000 {
|
||||
escaped.WriteRune('_')
|
||||
for s := 12; s >= 0; s -= 4 {
|
||||
escaped.WriteByte(lowerhex[b>>uint(s)&0xF])
|
||||
}
|
||||
escaped.WriteString(strconv.FormatInt(int64(b), 16))
|
||||
escaped.WriteRune('_')
|
||||
}
|
||||
}
|
||||
@@ -389,8 +381,9 @@ func UnescapeName(name string, scheme EscapingScheme) string {
|
||||
// We think we are in a UTF-8 code, process it.
|
||||
var utf8Val uint
|
||||
for j := 0; i < len(escapedName); j++ {
|
||||
// This is too many characters for a utf8 value.
|
||||
if j > 4 {
|
||||
// This is too many characters for a utf8 value based on the MaxRune
|
||||
// value of '\U0010FFFF'.
|
||||
if j >= 6 {
|
||||
return name
|
||||
}
|
||||
// Found a closing underscore, convert to a rune, check validity, and append.
|
||||
@@ -443,7 +436,7 @@ func (e EscapingScheme) String() string {
|
||||
|
||||
func ToEscapingScheme(s string) (EscapingScheme, error) {
|
||||
if s == "" {
|
||||
return NoEscaping, fmt.Errorf("got empty string instead of escaping scheme")
|
||||
return NoEscaping, errors.New("got empty string instead of escaping scheme")
|
||||
}
|
||||
switch s {
|
||||
case AllowUTF8:
|
||||
|
||||
17
vendor/github.com/prometheus/common/model/silence.go
generated
vendored
17
vendor/github.com/prometheus/common/model/silence.go
generated
vendored
@@ -15,6 +15,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
@@ -34,7 +35,7 @@ func (m *Matcher) UnmarshalJSON(b []byte) error {
|
||||
}
|
||||
|
||||
if len(m.Name) == 0 {
|
||||
return fmt.Errorf("label name in matcher must not be empty")
|
||||
return errors.New("label name in matcher must not be empty")
|
||||
}
|
||||
if m.IsRegex {
|
||||
if _, err := regexp.Compile(m.Value); err != nil {
|
||||
@@ -77,7 +78,7 @@ type Silence struct {
|
||||
// Validate returns true iff all fields of the silence have valid values.
|
||||
func (s *Silence) Validate() error {
|
||||
if len(s.Matchers) == 0 {
|
||||
return fmt.Errorf("at least one matcher required")
|
||||
return errors.New("at least one matcher required")
|
||||
}
|
||||
for _, m := range s.Matchers {
|
||||
if err := m.Validate(); err != nil {
|
||||
@@ -85,22 +86,22 @@ func (s *Silence) Validate() error {
|
||||
}
|
||||
}
|
||||
if s.StartsAt.IsZero() {
|
||||
return fmt.Errorf("start time missing")
|
||||
return errors.New("start time missing")
|
||||
}
|
||||
if s.EndsAt.IsZero() {
|
||||
return fmt.Errorf("end time missing")
|
||||
return errors.New("end time missing")
|
||||
}
|
||||
if s.EndsAt.Before(s.StartsAt) {
|
||||
return fmt.Errorf("start time must be before end time")
|
||||
return errors.New("start time must be before end time")
|
||||
}
|
||||
if s.CreatedBy == "" {
|
||||
return fmt.Errorf("creator information missing")
|
||||
return errors.New("creator information missing")
|
||||
}
|
||||
if s.Comment == "" {
|
||||
return fmt.Errorf("comment missing")
|
||||
return errors.New("comment missing")
|
||||
}
|
||||
if s.CreatedAt.IsZero() {
|
||||
return fmt.Errorf("creation timestamp missing")
|
||||
return errors.New("creation timestamp missing")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
3
vendor/github.com/prometheus/common/model/value_float.go
generated
vendored
3
vendor/github.com/prometheus/common/model/value_float.go
generated
vendored
@@ -15,6 +15,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
@@ -39,7 +40,7 @@ func (v SampleValue) MarshalJSON() ([]byte, error) {
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (v *SampleValue) UnmarshalJSON(b []byte) error {
|
||||
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
|
||||
return fmt.Errorf("sample value must be a quoted string")
|
||||
return errors.New("sample value must be a quoted string")
|
||||
}
|
||||
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
|
||||
if err != nil {
|
||||
|
||||
7
vendor/github.com/prometheus/common/model/value_histogram.go
generated
vendored
7
vendor/github.com/prometheus/common/model/value_histogram.go
generated
vendored
@@ -15,6 +15,7 @@ package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -32,7 +33,7 @@ func (v FloatString) MarshalJSON() ([]byte, error) {
|
||||
|
||||
func (v *FloatString) UnmarshalJSON(b []byte) error {
|
||||
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
|
||||
return fmt.Errorf("float value must be a quoted string")
|
||||
return errors.New("float value must be a quoted string")
|
||||
}
|
||||
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
|
||||
if err != nil {
|
||||
@@ -141,7 +142,7 @@ type SampleHistogramPair struct {
|
||||
|
||||
func (s SampleHistogramPair) MarshalJSON() ([]byte, error) {
|
||||
if s.Histogram == nil {
|
||||
return nil, fmt.Errorf("histogram is nil")
|
||||
return nil, errors.New("histogram is nil")
|
||||
}
|
||||
t, err := json.Marshal(s.Timestamp)
|
||||
if err != nil {
|
||||
@@ -164,7 +165,7 @@ func (s *SampleHistogramPair) UnmarshalJSON(buf []byte) error {
|
||||
return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen)
|
||||
}
|
||||
if s.Histogram == nil {
|
||||
return fmt.Errorf("histogram is null")
|
||||
return errors.New("histogram is null")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user