From 8affd293b49b336de7bbf0aafbf70cb38842e99a Mon Sep 17 00:00:00 2001 From: Andrew Glaude Date: Wed, 4 May 2022 11:08:58 -0400 Subject: [PATCH 1/4] contrib/sirupsen/logrus: Add context logging hook (#1240) --- contrib/sirupsen/logrus/example_test.go | 34 ++++++++++++++++++ contrib/sirupsen/logrus/logrus.go | 32 +++++++++++++++++ contrib/sirupsen/logrus/logrus_test.go | 31 +++++++++++++++++ go.mod | 2 +- go.sum | 46 +------------------------ 5 files changed, 99 insertions(+), 46 deletions(-) create mode 100644 contrib/sirupsen/logrus/example_test.go create mode 100644 contrib/sirupsen/logrus/logrus.go create mode 100644 contrib/sirupsen/logrus/logrus_test.go diff --git a/contrib/sirupsen/logrus/example_test.go b/contrib/sirupsen/logrus/example_test.go new file mode 100644 index 0000000000..4cafbcaebf --- /dev/null +++ b/contrib/sirupsen/logrus/example_test.go @@ -0,0 +1,34 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package logrus + +import ( + "context" + "os" + "time" + + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + "github.com/sirupsen/logrus" +) + +func ExampleHook() { + // Ensure your tracer is started and stopped + // Setup logrus, do this once at the beginning of your program + logrus.SetFormatter(&logrus.JSONFormatter{}) + logrus.AddHook(&DDContextLogHook{}) + logrus.SetOutput(os.Stdout) + + span, sctx := tracer.StartSpanFromContext(context.Background(), "mySpan") + defer span.Finish() + + // Pass the current span context to the logger (Time is set for consistency in output here) + cLog := logrus.WithContext(sctx).WithTime(time.Date(2000, 1, 1, 1, 1, 1, 0, time.UTC)) + // Log as desired using the context-aware logger + cLog.Info("Completed some work!") + // Output: + // {"dd.span_id":0,"dd.trace_id":0,"level":"info","msg":"Completed some work!","time":"2000-01-01T01:01:01Z"} +} diff --git a/contrib/sirupsen/logrus/logrus.go b/contrib/sirupsen/logrus/logrus.go new file mode 100644 index 0000000000..e3745b0014 --- /dev/null +++ b/contrib/sirupsen/logrus/logrus.go @@ -0,0 +1,32 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +// Package logrus provides a log/span correlation hook for the sirupsen/logrus package (https://github.com/sirupsen/logrus). +package logrus + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + "github.com/sirupsen/logrus" +) + +// DDContextLogHook ensures that any span in the log context is correlated to log output. +type DDContextLogHook struct{} + +// Levels implements logrus.Hook interface, this hook applies to all defined levels +func (d *DDContextLogHook) Levels() []logrus.Level { + return []logrus.Level{logrus.PanicLevel, logrus.FatalLevel, logrus.ErrorLevel, logrus.WarnLevel, logrus.InfoLevel, logrus.DebugLevel, logrus.TraceLevel} +} + +// Fire implements logrus.Hook interface, attaches trace and span details found in entry context +func (d *DDContextLogHook) Fire(e *logrus.Entry) error { + span, found := tracer.SpanFromContext(e.Context) + if !found { + return nil + } + e.Data["dd.trace_id"] = span.Context().TraceID() + e.Data["dd.span_id"] = span.Context().SpanID() + return nil +} diff --git a/contrib/sirupsen/logrus/logrus_test.go b/contrib/sirupsen/logrus/logrus_test.go new file mode 100644 index 0000000000..be23324b4d --- /dev/null +++ b/contrib/sirupsen/logrus/logrus_test.go @@ -0,0 +1,31 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package logrus + +import ( + "context" + "testing" + + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestFire(t *testing.T) { + tracer.Start() + defer tracer.Stop() + _, sctx := tracer.StartSpanFromContext(context.Background(), "testSpan", tracer.WithSpanID(1234)) + + hook := &DDContextLogHook{} + e := logrus.NewEntry(logrus.New()) + e.Context = sctx + err := hook.Fire(e) + + assert.NoError(t, err) + assert.Equal(t, uint64(1234), e.Data["dd.trace_id"]) + assert.Equal(t, uint64(1234), e.Data["dd.span_id"]) +} diff --git a/go.mod b/go.mod index 6e29ed8854..d0e2f882a1 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/philhofer/fwd v1.1.1 // indirect github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/segmentio/kafka-go v0.4.29 - github.com/stretchr/objx v0.2.0 // indirect + github.com/sirupsen/logrus v1.7.0 github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.0 github.com/tidwall/btree v1.1.0 // indirect diff --git a/go.sum b/go.sum index d04f1bf9a0..755b547091 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -26,7 +25,6 @@ cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1 cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/pubsub v1.4.0 h1:76oR7VBOkL7ivoIrFKyW0k7YDCRelrlxktIzQiIUGgg= cloud.google.com/go/pubsub v1.4.0/go.mod h1:LFrqilwgdw4X2cJS9ALgzYmMu+ULyrUN6IHV3CPK4TM= @@ -74,7 +72,6 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.0 h1:B7AQgHi8QSEi4uHu7Sbsga+IJDU+CENgjxoo81vDUqU= github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= @@ -107,9 +104,7 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -161,7 +156,6 @@ github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= @@ -169,7 +163,6 @@ github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -293,15 +286,12 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -316,7 +306,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -360,22 +349,18 @@ github.com/hashicorp/consul/api v1.0.0 h1:9GEZpB5zZ2Vm+rQ0t0JL/Ey2iaXbmIN1evA/LU github.com/hashicorp/consul/api v1.0.0/go.mod h1:mbFwfRxOTDHZpT3iUsMAFcLNoVm6Xbe1xZ6KiSm8FY0= github.com/hashicorp/consul/internal v0.1.0 h1:jNHZgWe9hbMO05/LRoJYHp/wWNiBwz+Ce6YlppiAEo8= github.com/hashicorp/consul/internal v0.1.0/go.mod h1:zi9bMZYbiPHyAjgBWo7kCUcy5l2NrTdrkVupCc7Oo6c= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -383,7 +368,6 @@ github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jU github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= @@ -405,7 +389,6 @@ github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -423,7 +406,6 @@ github.com/hashicorp/vault/api v1.1.0 h1:QcxC7FuqEl0sZaIjcXB/kNEeBa0DH5z57qbWBvZ github.com/hashicorp/vault/api v1.1.0/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk= github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 h1:e1ok06zGrWJW91rzRroyl5nRNqraaBe4d5hiKcVZuHM= github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= -github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -529,7 +511,6 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= @@ -547,7 +528,6 @@ github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8 github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/echo/v4 v4.2.0 h1:jkCSsjXmBmapVXF6U4BrSz/cgofWM0CU3Q74wQvXkIc= github.com/labstack/echo/v4 v4.2.0/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= -github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= @@ -569,7 +549,6 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= @@ -581,7 +560,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -593,7 +571,6 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/miekg/dns v1.1.25 h1:dFwPR6SfLtrSwgDcIq2bcU/gVutB4sNApq2HBdqcakg= github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -605,13 +582,10 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg= github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -628,7 +602,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -701,6 +674,7 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -856,7 +830,6 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20200901203048-c4f52b2c50aa h1:i1+omYRtqpxiCaQJB4MQhUToKvMPFqUUJKvRiRp0gtE= golang.org/x/exp v0.0.0-20200901203048-c4f52b2c50aa/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200908183739-ae8ad444f925 h1:5XVKs2rlCg8EFyRcvO8/XFwYxh1oKJO1Q3X5vttIf9c= golang.org/x/exp v0.0.0-20200908183739-ae8ad444f925/go.mod h1:1phAWC201xIgDyaFpmDeZkgf70Q4Pd/CNqfRtVPtxNw= @@ -880,7 +853,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 h1:xUIPaMhvROX9dhPvRCenIJtU78+lbEenGbgqB5hfHCQ= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -993,22 +965,16 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1020,7 +986,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -1086,7 +1051,6 @@ golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1101,10 +1065,8 @@ google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0 h1:J1Pl9P2lnmYFSJvgs70DKELqHNh8CNWXPbud4njEE2s= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.25.0 h1:LodzhlzZEUfhXzNUMIfVlf9Gr6Ua5MMtoFWh7+f47qA= google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= @@ -1166,16 +1128,13 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1197,12 +1156,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -1213,7 +1170,6 @@ gorm.io/driver/postgres v1.0.0/go.mod h1:wtMFcOzmuA5QigNsgEIb7O5lhvH1tHAF1RbWmLW gorm.io/driver/sqlserver v1.0.4 h1:V15fszi0XAo7fbx3/cF50ngshDSN4QT0MXpWTylyPTY= gorm.io/driver/sqlserver v1.0.4/go.mod h1:ciEo5btfITTBCj9BkoUVDvgQbUdLWQNqdFY5OGuGnRg= gorm.io/gorm v1.9.19/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.20.0 h1:qfIlyaZvrF7kMWY3jBdEBXkXJ2M5MFYMTppjILxS3fQ= gorm.io/gorm v1.20.0/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.20.6 h1:qa7tC1WcU+DBI/ZKMxvXy1FcrlGsvxlaKufHrT2qQ08= gorm.io/gorm v1.20.6/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= From 61462f045ea56920caf9922f46fb4b4d27ffb6a8 Mon Sep 17 00:00:00 2001 From: Andrew Glaude Date: Wed, 4 May 2022 11:58:56 -0400 Subject: [PATCH 2/4] README: clarify go version support policy (#1239) --- .circleci/config.yml | 55 ++++---------------------------- README.md | 47 ++++++++++++++++++++++++--- ddtrace/tracer/tracer.go | 9 ++++++ ddtrace/tracer/tracer_go11.go | 21 ------------ ddtrace/tracer/tracer_nongo11.go | 12 ------- go.mod | 2 +- profiler/options.go | 2 +- profiler/upload.go | 7 +--- 8 files changed, 62 insertions(+), 93 deletions(-) delete mode 100644 ddtrace/tracer/tracer_go11.go delete mode 100644 ddtrace/tracer/tracer_nongo11.go diff --git a/.circleci/config.yml b/.circleci/config.yml index bae0a7f30f..d991eb8742 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,48 +1,15 @@ version: 2.1 -plain-go114: &plain-go114 +plain-go114: &plain-go116 working_directory: /home/circleci/dd-trace-go.v1 docker: - - image: circleci/golang:1.14 + - image: circleci/golang:1.16 environment: GOPATH: "/home/circleci/go" jobs: - go1_12-build: - # Validate that the core builds with go1.12 - parameters: - build_tags: - description: "go build tags used to compile" - default: "" - type: string - goflags: - description: "extra goflags to pass to go test" - default: "" - type: string - docker: - - image: circleci/golang:1.12 - environment: - GOPATH: "/home/circleci/go" - working_directory: /home/circleci/dd-trace-go.v1 - environment: - # Go 1.12 doesn't have the proxy turned on by default but we need it to - # fetch some dependencies that aren't handled by fetching directly - # (such as github.com/go-chi/chi/v4@v4.0.0-rc1) - GOPROXY: "https://proxy.golang.org" - steps: - - checkout - - - run: - name: build - command: | - # Fixes fatal: unable to access 'https://gopkg.in/yaml.v3/': server certificate verification failed. CAfile: none CRLfile: none - # See https://github.com/DataDog/dd-trace-go/pull/1029 - sudo apt update && sudo apt install ca-certificates libgnutls30 -y - - go build -v -tags "<< parameters.build_tags >>" ./ddtrace/... ./profiler/... ./internal/appsec/... - metadata: - <<: *plain-go114 + <<: *plain-go116 steps: - checkout @@ -79,7 +46,7 @@ jobs: go run checkcopyright.go lint: - <<: *plain-go114 + <<: *plain-go116 steps: - checkout @@ -123,7 +90,7 @@ jobs: environment: # environment variables for the build itself TEST_RESULTS: /tmp/test-results # path to where test results will be saved DD_APPSEC_WAF_TIMEOUT: 1s - <<: *plain-go114 + <<: *plain-go116 steps: - checkout @@ -171,7 +138,7 @@ jobs: DD_APPSEC_WAF_TIMEOUT: 1s working_directory: /home/circleci/dd-trace-go.v1 docker: - - image: circleci/golang:1.14 + - image: circleci/golang:1.16 environment: GOPATH: "/home/circleci/go" - image: cassandra:3.7 @@ -334,6 +301,7 @@ jobs: name: Testing outlier google.golang.org/api command: | go get google.golang.org/grpc@v1.29.0 # https://github.com/grpc/grpc-go/issues/3726 + go mod tidy # Go1.16 doesn't update the sum file correctly after the go get, this tidy fixes it go test -v ./contrib/google.golang.org/api/... - run: @@ -368,10 +336,6 @@ workflows: version: 2 build-and-test: jobs: - - go1_12-build: - matrix: - parameters: - build_tags: [ "", "appsec" ] - metadata - lint - test-core: @@ -391,11 +355,6 @@ workflows: only: - v1 jobs: - - go1_12-build: - matrix: - parameters: - build_tags: [ "", "appsec" ] - goflags: [ "-race" ] - test-core: matrix: parameters: diff --git a/README.md b/README.md index 8b17a46434..c8627621fb 100644 --- a/README.md +++ b/README.md @@ -19,14 +19,53 @@ go get gopkg.in/DataDog/dd-trace-go.v1/contrib/gorilla/mux If you installed more packages than you intended, you can use `go mod tidy` to remove any unused packages. -Requires: +### Documentation + + - [API](https://pkg.go.dev/gopkg.in/DataDog/dd-trace-go.v1/ddtrace) + - [Tracing Go Applications](https://docs.datadoghq.com/tracing/setup/go/) + - [Continuous Go Profiler](https://docs.datadoghq.com/tracing/profiler/enabling/go). + - If you are migrating from an older version of the tracer (e.g. 0.6.x) you may also find the [migration document](MIGRATING.md) we've put together helpful. + +### Support Policy + +Datadog APM for Go is built upon dependencies defined in specific versions of the host operating system, Go releases, and the Datadog Agent/API. For Go the two latest releases are [GA](#support-ga) supported and the version before that is in [Maintenance](#support-maintenance). We do make efforts to support older releases, but generally these releases are considered [Legacy](#support-legacy). This library only officially supports [first class ports](https://github.com/golang/go/wiki/PortingPolicy#first-class-ports) of Go. + +| **Level** | **Support provided** | +|--------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| General Availability (GA) | Full implementation of all features. Full support for new features, bug & security fixes. | +| Maintenance | Full implementation of existing features. May receive new features. Support for bug & security fixes only. | +| Legacy | Legacy implementation. May have limited function, but no maintenance provided. [Contact our customer support team for special requests.](https://www.datadoghq.com/support/) | + +### Supported Versions + +| **Go Version** | **Support level** | +|----------------|-------------------------------------| +| 1.18 | [GA](#support-ga) | +| 1.17 | [GA](#support-ga) | +| 1.16 | [Maintenance](#support-maintenance) | -* Go >= 1.12 * Datadog's Trace Agent >= 5.21.1 -### Documentation +#### Package Versioning + +A **Minor** version change will be released whenever a new version of Go is released. At that time the newest version of Go is added to [GA](#support-ga), the second oldest supported version moved to [Maintenance](#support-maintenance) and the oldest previously supported version dropped to [Legacy](#support-legacy). +**For example**: +For a dd-trace-go version 1.37.* + +| Go Version | Support | +|------------|-------------------------------------| +| 1.18 | [GA](#support-ga) | +| 1.17 | [GA](#support-ga) | +| 1.16 | [Maintenance](#support-maintenance) | + +Then after Go 1.19 is released there will be a new dd-trace-go version 1.38.0 with support: -The API is documented on [godoc](https://godoc.org/gopkg.in/DataDog/dd-trace-go.v1/ddtrace) as well as Datadog's official documentation for [Tracing Go Applications](https://docs.datadoghq.com/tracing/setup/go/) and the [Continuous Go Profiler](https://docs.datadoghq.com/tracing/profiler/enabling/go). If you are migrating from an older version of the tracer (e.g. 0.6.x) you may also find the [migration document](MIGRATING.md) we've put together helpful. +| Go Version | Support | +|------------|-------------------------------------| +| 1.19 | [GA](#support-ga) | +| 1.18 | [GA](#support-ga) | +| 1.17 | [Maintenance](#support-maintenance) | +| 1.16 | [Legacy](#support-legacy) | ### Contributing diff --git a/ddtrace/tracer/tracer.go b/ddtrace/tracer/tracer.go index ee42a81204..ee32b00efb 100644 --- a/ddtrace/tracer/tracer.go +++ b/ddtrace/tracer/tracer.go @@ -9,6 +9,7 @@ import ( gocontext "context" "os" "runtime/pprof" + rt "runtime/trace" "strconv" "sync" "time" @@ -526,3 +527,11 @@ func (t *tracer) sample(span *span) { } t.prioritySampling.apply(span) } + +func startExecutionTracerTask(name string) func() { + if !rt.IsEnabled() { + return func() {} + } + _, task := rt.NewTask(gocontext.TODO(), name) + return task.End +} diff --git a/ddtrace/tracer/tracer_go11.go b/ddtrace/tracer/tracer_go11.go deleted file mode 100644 index ac8cd8cc87..0000000000 --- a/ddtrace/tracer/tracer_go11.go +++ /dev/null @@ -1,21 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016 Datadog, Inc. - -// +build go1.11 - -package tracer - -import ( - "context" - t "runtime/trace" -) - -func startExecutionTracerTask(name string) func() { - if !t.IsEnabled() { - return func() {} - } - _, task := t.NewTask(context.TODO(), name) - return task.End -} diff --git a/ddtrace/tracer/tracer_nongo11.go b/ddtrace/tracer/tracer_nongo11.go deleted file mode 100644 index ccf8b9f98e..0000000000 --- a/ddtrace/tracer/tracer_nongo11.go +++ /dev/null @@ -1,12 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016 Datadog, Inc. - -// +build !go1.11 - -package tracer - -func startExecutionTracerTask(name string) func() { - return func() {} -} diff --git a/go.mod b/go.mod index d0e2f882a1..4abae052dc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module gopkg.in/DataDog/dd-trace-go.v1 -go 1.12 +go 1.16 require ( cloud.google.com/go/pubsub v1.4.0 diff --git a/profiler/options.go b/profiler/options.go index 1e6c0551fe..8106b61531 100644 --- a/profiler/options.go +++ b/profiler/options.go @@ -116,7 +116,7 @@ func logStartup(c *config) { OSVersion string `json:"os_version"` // Version of the OS Version string `json:"version"` // Profiler version Lang string `json:"lang"` // "Go" - LangVersion string `json:"lang_version"` // Go version, e.g. go1.13 + LangVersion string `json:"lang_version"` // Go version, e.g. go1.18 Hostname string `json:"hostname"` DeltaProfiles bool `json:"delta_profiles"` Service string `json:"service"` diff --git a/profiler/upload.go b/profiler/upload.go index d023ad396f..dfc92863b3 100644 --- a/profiler/upload.go +++ b/profiler/upload.go @@ -87,12 +87,7 @@ func (p *profiler) doRequest(bat batch) error { } cancel() }() - // TODO(fg) use NewRequestWithContext once go 1.12 support is dropped. - req, err := http.NewRequest("POST", p.cfg.targetURL, body) - if err != nil { - return err - } - req = req.WithContext(ctx) + req, err := http.NewRequestWithContext(ctx, "POST", p.cfg.targetURL, body) if p.cfg.apiKey != "" { req.Header.Set("DD-API-KEY", p.cfg.apiKey) } From 3de9a7dfa8800c0709956ab7432e0ca69efabd0d Mon Sep 17 00:00:00 2001 From: Nick Ripley <97066770+nsrip-dd@users.noreply.github.com> Date: Thu, 5 May 2022 08:43:16 -0400 Subject: [PATCH 3/4] profiler: add extension hook for C allocation profiling (#1264) This is a first pass at adding an internal bridge for integrating C allocation profiling with the regular heap profile. C allocation profiling will require cgo and possibly other external dependencies and non-standard linker flags. As such, the main profiler package should not directly import the C allocation profiler implementation. But there still needs to be some way to actually _use_ the allocation profiler if it's available. This commit adds a bridge for doing so, and makes a few changes to enable actually running the profile and merging it with the heap profile. --- profiler/internal/extensions/extensions.go | 60 ++++++++++ profiler/internal/pprofutils/delta.go | 10 +- profiler/profile.go | 130 +++++++++++---------- profiler/profiler.go | 18 +-- 4 files changed, 147 insertions(+), 71 deletions(-) create mode 100644 profiler/internal/extensions/extensions.go diff --git a/profiler/internal/extensions/extensions.go b/profiler/internal/extensions/extensions.go new file mode 100644 index 0000000000..b449c52700 --- /dev/null +++ b/profiler/internal/extensions/extensions.go @@ -0,0 +1,60 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +// Package extensions provides an interface for using optional features. +// +// Features such as C allocation profiling might require cgo, unsafe code, and +// external non-Go dependencies which might not be desirable for typical users. +// The main profiler package should not import any package implementing such +// features directly as doing so may have undesired side effects. This package +// provides a bridge between the implementation of such optional features and +// the main profiler package. +package extensions + +import ( + "sync" + + "github.com/google/pprof/profile" +) + +// CAllocationProfiler is the interface for profiling allocations done through +// the standard malloc/calloc/realloc APIs. +// +// A CAllocationProfiler implementation is not necessarily safe to use from +// multiple goroutines concurrently. +type CAllocationProfiler interface { + // Start begins sampling C allocations at the given rate, in bytes. + // There will be an average of one sample for every rate bytes + // allocated. + Start(rate int) + // Stop cancels ongoing C allocation profiling and returns the resulting + // profile. The profile will have the correct sample types such that it + // can be merged with the Go heap profile. Returns a non-nil error if + // any part of the profiling failed. + Stop() (*profile.Profile, error) +} + +var ( + mu sync.Mutex + cAllocationProfiler CAllocationProfiler +) + +// GetCAllocationProfiler returns the currently registered C allocation +// profiler, if one is registered. +func GetCAllocationProfiler() (impl CAllocationProfiler, registered bool) { + mu.Lock() + defer mu.Unlock() + if cAllocationProfiler == nil { + return nil, false + } + return cAllocationProfiler, true +} + +// SetCAllocationProfiler registers a C allocation profiler implementation. +func SetCAllocationProfiler(c CAllocationProfiler) { + mu.Lock() + defer mu.Unlock() + cAllocationProfiler = c +} diff --git a/profiler/internal/pprofutils/delta.go b/profiler/internal/pprofutils/delta.go index 1326db36b7..263668bd9c 100644 --- a/profiler/internal/pprofutils/delta.go +++ b/profiler/internal/pprofutils/delta.go @@ -30,7 +30,10 @@ type Delta struct { // profile. Samples that end up with a delta of 0 are dropped. WARNING: Profile // a will be mutated by this function. You should pass a copy if that's // undesirable. -func (d Delta) Convert(a, b *profile.Profile) (*profile.Profile, error) { +// +// Other profiles that should be merged into the resulting profile can be passed +// through the extra parameter. +func (d Delta) Convert(a, b *profile.Profile, extra ...*profile.Profile) (*profile.Profile, error) { ratios := make([]float64, len(a.SampleType)) found := 0 @@ -58,7 +61,10 @@ func (d Delta) Convert(a, b *profile.Profile) (*profile.Profile, error) { a.ScaleN(ratios) - delta, err := profile.Merge([]*profile.Profile{a, b}) + profiles := make([]*profile.Profile, 0, 2+len(extra)) + profiles = append(profiles, a, b) + profiles = append(profiles, extra...) + delta, err := profile.Merge(profiles) if err != nil { return nil, err } diff --git a/profiler/profile.go b/profiler/profile.go index 038d077dc8..5c6eaa1cf1 100644 --- a/profiler/profile.go +++ b/profiler/profile.go @@ -13,6 +13,7 @@ import ( "runtime" "time" + "gopkg.in/DataDog/dd-trace-go.v1/profiler/internal/extensions" "gopkg.in/DataDog/dd-trace-go.v1/profiler/internal/pprofutils" "github.com/DataDog/gostackparse" @@ -63,14 +64,12 @@ type profileType struct { // this isn't done due to idiosyncratic filename used by the // GoroutineProfile. Filename string - // Delta controls if this profile should be generated as a delta profile. - // This is useful for profiles that represent samples collected over the - // lifetime of the process (i.e. heap, block, mutex). If nil, no delta - // profile is generated. - Delta *pprofutils.Delta + // SupportsDelta indicates whether delta profiles can be computed for + // this profile type, which is used to determine the final filename + SupportsDelta bool // Collect collects the given profile and returns the data for it. Most // profiles will be in pprof format, i.e. gzip compressed proto buf data. - Collect func(profileType, *profiler) ([]byte, error) + Collect func(p *profiler) ([]byte, error) } // profileTypes maps every ProfileType to its implementation. @@ -78,7 +77,7 @@ var profileTypes = map[ProfileType]profileType{ CPUProfile: { Name: "cpu", Filename: "cpu.pprof", - Collect: func(_ profileType, p *profiler) ([]byte, error) { + Collect: func(p *profiler) ([]byte, error) { var buf bytes.Buffer if p.cfg.cpuProfileRate != 0 { // The profile has to be set each time before @@ -103,33 +102,33 @@ var profileTypes = map[ProfileType]profileType{ HeapProfile: { Name: "heap", Filename: "heap.pprof", - Delta: &pprofutils.Delta{SampleTypes: []pprofutils.ValueType{ + Collect: collectGenericProfile("heap", &pprofutils.Delta{SampleTypes: []pprofutils.ValueType{ {Type: "alloc_objects", Unit: "count"}, {Type: "alloc_space", Unit: "bytes"}, - }}, - Collect: collectGenericProfile, + }}), + SupportsDelta: true, }, MutexProfile: { - Name: "mutex", - Filename: "mutex.pprof", - Delta: &pprofutils.Delta{}, - Collect: collectGenericProfile, + Name: "mutex", + Filename: "mutex.pprof", + Collect: collectGenericProfile("mutex", &pprofutils.Delta{}), + SupportsDelta: true, }, BlockProfile: { - Name: "block", - Filename: "block.pprof", - Delta: &pprofutils.Delta{}, - Collect: collectGenericProfile, + Name: "block", + Filename: "block.pprof", + Collect: collectGenericProfile("block", &pprofutils.Delta{}), + SupportsDelta: true, }, GoroutineProfile: { Name: "goroutine", Filename: "goroutines.pprof", - Collect: collectGenericProfile, + Collect: collectGenericProfile("goroutine", nil), }, expGoroutineWaitProfile: { Name: "goroutinewait", Filename: "goroutineswait.pprof", - Collect: func(t profileType, p *profiler) ([]byte, error) { + Collect: func(p *profiler) ([]byte, error) { if n := runtime.NumGoroutine(); n > p.cfg.maxGoroutinesWait { return nil, fmt.Errorf("skipping goroutines wait profile: %d goroutines exceeds DD_PROFILING_WAIT_PROFILE_MAX_GOROUTINES limit of %d", n, p.cfg.maxGoroutinesWait) } @@ -149,7 +148,7 @@ var profileTypes = map[ProfileType]profileType{ MetricsProfile: { Name: "metrics", Filename: "metrics.json", - Collect: func(_ profileType, p *profiler) ([]byte, error) { + Collect: func(p *profiler) ([]byte, error) { var buf bytes.Buffer err := p.met.report(now(), &buf) return buf.Bytes(), err @@ -157,10 +156,42 @@ var profileTypes = map[ProfileType]profileType{ }, } -func collectGenericProfile(t profileType, p *profiler) ([]byte, error) { - var buf bytes.Buffer - err := p.lookupProfile(t.Name, &buf, 0) - return buf.Bytes(), err +func collectGenericProfile(name string, delta *pprofutils.Delta) func(p *profiler) ([]byte, error) { + return func(p *profiler) ([]byte, error) { + var extra []*pprofile.Profile + // TODO: add type safety for name == "heap" check and remove redunancy with profileType.Name. + if cAlloc, ok := extensions.GetCAllocationProfiler(); ok && p.cfg.deltaProfiles && name == "heap" { + // For the heap profile, we'd also like to include C + // allocations if that extension is enabled and have the + // allocations show up in the same profile. Collect them + // first before getting the regular heap snapshot so + // that all allocations cover the same time period + // + // TODO: Support non-delta profiles for C allocations? + cAlloc.Start(2 * 1024 * 1024) + p.interruptibleSleep(p.cfg.period) + profile, err := cAlloc.Stop() + if err == nil { + extra = append(extra, profile) + } + } + + var buf bytes.Buffer + err := p.lookupProfile(name, &buf, 0) + data := buf.Bytes() + if delta == nil || !p.cfg.deltaProfiles { + return data, err + } + + start := time.Now() + delta, err := p.deltaProfile(name, delta, data, extra...) + tags := append(p.cfg.tags, fmt.Sprintf("profile_type:%s", name)) + p.cfg.statsd.Timing("datadog.profiler.go.delta_time", time.Since(start), tags, 1) + if err != nil { + return nil, fmt.Errorf("delta profile error: %s", err) + } + return delta.data, err + } } // lookup returns t's profileType implementation. @@ -174,7 +205,7 @@ func (t ProfileType) lookup() profileType { Type: t, Name: "unknown", Filename: "unknown", - Collect: func(_ profileType, _ *profiler) ([]byte, error) { + Collect: func(_ *profiler) ([]byte, error) { return nil, errors.New("profile type not implemented") }, } @@ -217,49 +248,31 @@ func (b *batch) addProfile(p *profile) { func (p *profiler) runProfile(pt ProfileType) ([]*profile, error) { start := now() t := pt.lookup() - // Collect the original profile as-is. - data, err := t.Collect(t, p) + data, err := t.Collect(p) if err != nil { return nil, err } - // Compute the deltaProf (will be nil if not enabled for this profile type). - deltaStart := time.Now() - deltaProf, err := p.deltaProfile(t, data) - if err != nil { - return nil, fmt.Errorf("delta profile error: %s", err) - } end := now() tags := append(p.cfg.tags, pt.Tag()) - var profs []*profile - if deltaProf != nil { - profs = append(profs, deltaProf) - p.cfg.statsd.Timing("datadog.profiler.go.delta_time", end.Sub(deltaStart), tags, 1) - } else { - // If the user has disabled delta profiles, or the profile type - // doesn't support delta profiles (like the CPU profile) then - // send the original profile unchanged. - profs = append(profs, &profile{ - name: t.Filename, - data: data, - }) + filename := t.Filename + // TODO(fg): Consider making Collect() return the filename. + if p.cfg.deltaProfiles && t.SupportsDelta { + filename = "delta-" + filename } p.cfg.statsd.Timing("datadog.profiler.go.collect_time", end.Sub(start), tags, 1) - return profs, nil + return []*profile{{name: filename, data: data}}, nil } // deltaProfile derives the delta profile between curData and the previous -// profile. For profile types that don't have delta profiling enabled, or -// WithDeltaProfiles(false), it simply returns nil, nil. -func (p *profiler) deltaProfile(t profileType, curData []byte) (*profile, error) { - if !p.cfg.deltaProfiles || t.Delta == nil { - return nil, nil - } +// profile. If extra profiles are provided, they will be merged into the final +// profile after computing the delta profile. +func (p *profiler) deltaProfile(name string, delta *pprofutils.Delta, curData []byte, extra ...*pprofile.Profile) (*profile, error) { curProf, err := pprofile.ParseData(curData) if err != nil { return nil, fmt.Errorf("delta prof parse: %v", err) } var deltaData []byte - if prevProf := p.prev[t.Type]; prevProf == nil { + if prevProf := p.prev[name]; prevProf == nil { // First time deltaProfile gets called for a type, there is no prevProf. In // this case we emit the current profile as a delta profile. deltaData = curData @@ -268,7 +281,7 @@ func (p *profiler) deltaProfile(t profileType, curData []byte) (*profile, error) // Unfortunately the core implementation isn't resuable via a API, so we do // our own delta calculation below. // https://github.com/golang/go/commit/2ff1e3ebf5de77325c0e96a6c2a229656fc7be50#diff-94594f8f13448da956b02997e50ca5a156b65085993e23bbfdda222da6508258R303-R304 - deltaProf, err := t.Delta.Convert(prevProf, curProf) + deltaProf, err := delta.Convert(prevProf, curProf, extra...) if err != nil { return nil, fmt.Errorf("delta prof merge: %v", err) } @@ -285,11 +298,8 @@ func (p *profiler) deltaProfile(t profileType, curData []byte) (*profile, error) } // Keep the most recent profiles in memory for future diffing. This needs to // be taken into account when enforcing memory limits going forward. - p.prev[t.Type] = curProf - return &profile{ - name: "delta-" + t.Filename, - data: deltaData, - }, nil + p.prev[name] = curProf + return &profile{data: deltaData}, nil } func goroutineDebug2ToPprof(r io.Reader, w io.Writer, t time.Time) (err error) { diff --git a/profiler/profiler.go b/profiler/profiler.go index 4e33a6d998..d5d6f4bbee 100644 --- a/profiler/profiler.go +++ b/profiler/profiler.go @@ -63,14 +63,14 @@ func Stop() { // profiler collects and sends preset profiles to the Datadog API at a given frequency // using a given configuration. type profiler struct { - cfg *config // profile configuration - out chan batch // upload queue - uploadFunc func(batch) error // defaults to (*profiler).upload; replaced in tests - exit chan struct{} // exit signals the profiler to stop; it is closed after stopping - stopOnce sync.Once // stopOnce ensures the profiler is stopped exactly once. - wg sync.WaitGroup // wg waits for all goroutines to exit when stopping. - met *metrics // metric collector state - prev map[ProfileType]*pprofile.Profile // previous collection results for delta profiling + cfg *config // profile configuration + out chan batch // upload queue + uploadFunc func(batch) error // defaults to (*profiler).upload; replaced in tests + exit chan struct{} // exit signals the profiler to stop; it is closed after stopping + stopOnce sync.Once // stopOnce ensures the profiler is stopped exactly once. + wg sync.WaitGroup // wg waits for all goroutines to exit when stopping. + met *metrics // metric collector state + prev map[string]*pprofile.Profile // previous collection results for delta profiling testHooks testHooks } @@ -178,7 +178,7 @@ func newProfiler(opts ...Option) (*profiler, error) { out: make(chan batch, outChannelSize), exit: make(chan struct{}), met: newMetrics(), - prev: make(map[ProfileType]*pprofile.Profile), + prev: make(map[string]*pprofile.Profile), } p.uploadFunc = p.upload return &p, nil From 1c53df517eb5d7d23d083ca3aecc986026d8246f Mon Sep 17 00:00:00 2001 From: Nick Ripley <97066770+nsrip-dd@users.noreply.github.com> Date: Thu, 5 May 2022 09:02:54 -0400 Subject: [PATCH 4/4] profiler: make TestSetProfileFraction more isolated (#1281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TestAllUploaded starts the mutex profiler. Currently the profiler doesn't re-set the profile rate when Stop is called. This causes TestSetProfileFraction/on to fail if it's run after TestAllUploaded since the test checks that the old rate is different than the new rate, but in both cases the rates are the default rate. This commit changes the test to start by setting the rate to 0 and then checking that it's either the default value or still 0 after starting the profiler. This makes the test more isolated and not influenced by what other tests do to the mutex profile fraction. Fixes #1279 Co-authored-by: Felix Geisendörfer --- profiler/profiler_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/profiler/profiler_test.go b/profiler/profiler_test.go index 48d919ab2c..7573eac4f9 100644 --- a/profiler/profiler_test.go +++ b/profiler/profiler_test.go @@ -277,23 +277,23 @@ func TestProfilerInternal(t *testing.T) { func TestSetProfileFraction(t *testing.T) { t.Run("on", func(t *testing.T) { - start := runtime.SetMutexProfileFraction(-1) + start := runtime.SetMutexProfileFraction(0) defer runtime.SetMutexProfileFraction(start) p, err := unstartedProfiler(WithProfileTypes(MutexProfile)) require.NoError(t, err) p.run() p.stop() - assert.NotEqual(t, start, runtime.SetMutexProfileFraction(-1)) + assert.Equal(t, DefaultMutexFraction, runtime.SetMutexProfileFraction(-1)) }) t.Run("off", func(t *testing.T) { - start := runtime.SetMutexProfileFraction(-1) + start := runtime.SetMutexProfileFraction(0) defer runtime.SetMutexProfileFraction(start) p, err := unstartedProfiler() require.NoError(t, err) p.run() p.stop() - assert.Equal(t, start, runtime.SetMutexProfileFraction(-1)) + assert.Zero(t, runtime.SetMutexProfileFraction(-1)) }) }