forked from open-telemetry/opentelemetry-go-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into pullrequests/MikeGoldsmith/macaron-plugin
* master: Runtime metrics plugin (open-telemetry#9) Fix issues raised by golangci-lint (open-telemetry#29) use correct circleci dir (open-telemetry#30) gorilla/mux instrumentation (open-telemetry#19) Update CODEOWNERS and CONTRIBUTING.md to match otel-go (open-telemetry#27) Dogstatsd exporter resource support (for 0.4.3 release) (open-telemetry#25) add datadog metrics exporter (open-telemetry#22) Update codeowners and maintainers (open-telemetry#21) # Conflicts: # go.mod # go.sum # internal/trace/http.go
- Loading branch information
Showing
35 changed files
with
1,636 additions
and
133 deletions.
There are no files selected for viewing
File renamed without changes.
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
package datadog | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"regexp" | ||
|
||
"github.com/DataDog/datadog-go/statsd" | ||
|
||
"go.opentelemetry.io/otel/api/core" | ||
export "go.opentelemetry.io/otel/sdk/export/metric" | ||
"go.opentelemetry.io/otel/sdk/export/metric/aggregator" | ||
) | ||
|
||
const ( | ||
// DefaultStatsAddrUDP specifies the default protocol (UDP) and address | ||
// for the DogStatsD service. | ||
DefaultStatsAddrUDP = "localhost:8125" | ||
) | ||
|
||
// NewExporter exports to a datadog client | ||
func NewExporter(opts Options) (*Exporter, error) { | ||
if opts.StatsAddr == "" { | ||
opts.StatsAddr = DefaultStatsAddrUDP | ||
} | ||
if opts.MetricNameFormatter == nil { | ||
opts.MetricNameFormatter = defaultFormatter | ||
} | ||
client, err := statsd.New(opts.StatsAddr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &Exporter{ | ||
client: client, | ||
opts: opts, | ||
}, nil | ||
} | ||
|
||
// Options contains options for configuring the exporter. | ||
type Options struct { | ||
// StatsAddr specifies the host[:port] address for DogStatsD. It defaults | ||
// to localhost:8125. | ||
StatsAddr string | ||
|
||
// Tags specifies a set of global tags to attach to each metric. | ||
Tags []string | ||
|
||
// UseDistribution uses a DataDog Distribution type instead of Histogram | ||
UseDistribution bool | ||
|
||
// MetricNameFormatter lets you customize the metric name that gets sent to | ||
// datadog before exporting | ||
MetricNameFormatter func(namespace, name string) string | ||
} | ||
|
||
// Exporter forwards metrics to a DataDog agent | ||
type Exporter struct { | ||
opts Options | ||
client *statsd.Client | ||
} | ||
|
||
const rate = 1 | ||
|
||
func defaultFormatter(namespace, name string) string { | ||
return name | ||
} | ||
|
||
func (e *Exporter) Export(ctx context.Context, cs export.CheckpointSet) error { | ||
return cs.ForEach(func(r export.Record) error { | ||
agg := r.Aggregator() | ||
name := e.sanitizeMetricName(r.Descriptor().LibraryName(), r.Descriptor().Name()) | ||
itr := r.Labels().Iter() | ||
tags := append([]string{}, e.opts.Tags...) | ||
for itr.Next() { | ||
label := itr.Label() | ||
tag := string(label.Key) + ":" + label.Value.Emit() | ||
tags = append(tags, tag) | ||
} | ||
switch agg := agg.(type) { | ||
case aggregator.Points: | ||
numbers, err := agg.Points() | ||
if err != nil { | ||
return fmt.Errorf("error getting Points for %s: %w", name, err) | ||
} | ||
f := e.client.Histogram | ||
if e.opts.UseDistribution { | ||
f = e.client.Distribution | ||
} | ||
for _, n := range numbers { | ||
if err := f(name, metricValue(r.Descriptor().NumberKind(), n), tags, rate); err != nil { | ||
return fmt.Errorf("error submitting %s point: %w", name, err) | ||
} | ||
} | ||
case aggregator.MinMaxSumCount: | ||
type record struct { | ||
name string | ||
f func() (core.Number, error) | ||
} | ||
recs := []record{ | ||
{ | ||
name: name + ".min", | ||
f: agg.Min, | ||
}, | ||
{ | ||
name: name + ".max", | ||
f: agg.Max, | ||
}, | ||
} | ||
if dist, ok := agg.(aggregator.Distribution); ok { | ||
recs = append(recs, | ||
record{name: name + ".median", f: func() (core.Number, error) { | ||
return dist.Quantile(0.5) | ||
}}, | ||
record{name: name + ".p95", f: func() (core.Number, error) { | ||
return dist.Quantile(0.95) | ||
}}, | ||
) | ||
} | ||
for _, rec := range recs { | ||
val, err := rec.f() | ||
if err != nil { | ||
return fmt.Errorf("error getting MinMaxSumCount value for %s: %w", name, err) | ||
} | ||
if err := e.client.Gauge(rec.name, metricValue(r.Descriptor().NumberKind(), val), tags, rate); err != nil { | ||
return fmt.Errorf("error submitting %s point: %w", name, err) | ||
} | ||
} | ||
case aggregator.Sum: | ||
val, err := agg.Sum() | ||
if err != nil { | ||
return fmt.Errorf("error getting Sum value for %s: %w", name, err) | ||
} | ||
if err := e.client.Count(name, val.AsInt64(), tags, rate); err != nil { | ||
return fmt.Errorf("error submitting %s point: %w", name, err) | ||
} | ||
case aggregator.LastValue: | ||
val, _, err := agg.LastValue() | ||
if err != nil { | ||
return fmt.Errorf("error getting LastValue for %s: %w", name, err) | ||
} | ||
if err := e.client.Gauge(name, metricValue(r.Descriptor().NumberKind(), val), tags, rate); err != nil { | ||
return fmt.Errorf("error submitting %s point: %w", name, err) | ||
} | ||
} | ||
return nil | ||
}) | ||
} | ||
|
||
// Close cloess the underlying datadog client which flushes | ||
// any pending buffers | ||
func (e *Exporter) Close() error { | ||
return e.client.Close() | ||
} | ||
|
||
// sanitizeMetricName formats the custom namespace and view name to | ||
// Datadog's metric naming convention | ||
func (e *Exporter) sanitizeMetricName(namespace, name string) string { | ||
return sanitizeString(e.opts.MetricNameFormatter(namespace, name)) | ||
} | ||
|
||
// regex pattern | ||
var reg = regexp.MustCompile("[^a-zA-Z0-9]+") | ||
|
||
// sanitizeString replaces all non-alphanumerical characters to underscore | ||
func sanitizeString(str string) string { | ||
return reg.ReplaceAllString(str, "_") | ||
} | ||
|
||
func metricValue(kind core.NumberKind, number core.Number) float64 { | ||
switch kind { | ||
case core.Float64NumberKind: | ||
return number.AsFloat64() | ||
case core.Int64NumberKind: | ||
return float64(number.AsInt64()) | ||
case core.Uint64NumberKind: | ||
return float64(number.AsUint64()) | ||
} | ||
return float64(number) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package datadog_test | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/DataDog/sketches-go/ddsketch" | ||
|
||
"go.opentelemetry.io/contrib/exporters/metric/datadog" | ||
"go.opentelemetry.io/otel/api/global" | ||
"go.opentelemetry.io/otel/api/metric" | ||
export "go.opentelemetry.io/otel/sdk/export/metric" | ||
"go.opentelemetry.io/otel/sdk/metric/batcher/ungrouped" | ||
"go.opentelemetry.io/otel/sdk/metric/controller/push" | ||
"go.opentelemetry.io/otel/sdk/metric/selector/simple" | ||
) | ||
|
||
func ExampleExporter() { | ||
selector := simple.NewWithSketchMeasure(ddsketch.NewDefaultConfig()) | ||
batcher := ungrouped.New(selector, export.NewDefaultLabelEncoder(), false) | ||
exp, err := datadog.NewExporter(datadog.Options{ | ||
Tags: []string{"env:dev"}, | ||
}) | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer exp.Close() | ||
pusher := push.New(batcher, exp, time.Second*10) | ||
defer pusher.Stop() | ||
pusher.Start() | ||
global.SetMeterProvider(pusher) | ||
meter := global.Meter("marwandist") | ||
m := metric.Must(meter).NewInt64Counter("mycounter") | ||
meter.RecordBatch(context.Background(), nil, m.Measurement(19)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module go.opentelemetry.io/contrib/exporters/metric/datadog | ||
|
||
go 1.14 | ||
|
||
require ( | ||
github.com/DataDog/datadog-go v3.5.0+incompatible | ||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7 | ||
go.opentelemetry.io/otel v0.4.2 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | ||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||
github.com/DataDog/datadog-go v3.5.0+incompatible h1:AShr9cqkF+taHjyQgcBcQUt/ZNK+iPq4ROaZwSX5c/U= | ||
github.com/DataDog/datadog-go v3.5.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= | ||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7 h1:qELHH0AWCvf98Yf+CNIJx9vOZOfHFDDzgDRYsnNk/vs= | ||
github.com/DataDog/sketches-go v0.0.0-20190923095040-43f19ad77ff7/go.mod h1:Q5DbzQ+3AkgGwymQO7aZFNP7ns2lZKGtvRBzRXfdi60= | ||
github.com/benbjohnson/clock v1.0.0 h1:78Jk/r6m4wCi6sndMpty7A//t4dw/RW5fV4ZgDVfX1w= | ||
github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= | ||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | ||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= | ||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | ||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | ||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= | ||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | ||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | ||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= | ||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= | ||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | ||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||
github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | ||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | ||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||
go.opentelemetry.io/otel v0.4.2 h1:nT+GOqqRR1cIY92xmo1DeiXLHtIlXH1KLRgnsnhuNrs= | ||
go.opentelemetry.io/otel v0.4.2/go.mod h1:OgNpQOjrlt33Ew6Ds0mGjmcTQg/rhUctsbkRdk/g1fw= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | ||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | ||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | ||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | ||
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= | ||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | ||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | ||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | ||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= | ||
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 h1:4HYDjxeNXAOTv3o1N2tjo8UUSlhQgAD52FVkwxnWgM8= | ||
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= | ||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | ||
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= | ||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= | ||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= |
Oops, something went wrong.