diff --git a/.gitignore b/.gitignore index 6529e9498..997aa63a7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -.tools/ \ No newline at end of file +.tools/ +.idea/ +*.iml +*.so diff --git a/api/core/core.go b/api/core/core.go index dce685f2c..0fa0bd002 100644 --- a/api/core/core.go +++ b/api/core/core.go @@ -17,6 +17,9 @@ package core import ( "context" "fmt" + "strconv" + + "google.golang.org/grpc/codes" "github.com/open-telemetry/opentelemetry-go/api/unit" ) @@ -132,6 +135,12 @@ const ( DELETE ) +var ( + // INVALID_SPAN_CONTEXT is meant for internal use to return invalid span context during error + // conditions. + INVALID_SPAN_CONTEXT = SpanContext{} +) + func (sc SpanContext) HasTraceID() bool { return sc.TraceIDHigh != 0 || sc.TraceIDLow != 0 } @@ -191,3 +200,44 @@ func (m Measurement) With(id ScopeID) Measurement { m.ScopeID = id return m } + +func GrpcCodeToString(s codes.Code) string { + switch c := s; c { + case codes.OK: + return "OK" + case codes.Canceled: + return "CANCELLED" + case codes.Unknown: + return "UNKNOWN" + case codes.InvalidArgument: + return "INVALID_ARGUMENT" + case codes.DeadlineExceeded: + return "DEADLINE_EXCEEDED" + case codes.NotFound: + return "NOT_FOUND" + case codes.AlreadyExists: + return "ALREADY_EXISTS" + case codes.PermissionDenied: + return "PERMISSION_DENIED" + case codes.ResourceExhausted: + return "RESOURCE_EXHAUSTED" + case codes.FailedPrecondition: + return "FAILED_PRECONDITION" + case codes.Aborted: + return "ABORTED" + case codes.OutOfRange: + return "OUT_OF_RANGE" + case codes.Unimplemented: + return "UNIMPLEMENTED" + case codes.Internal: + return "INTERNAL" + case codes.Unavailable: + return "UNAVAILABLE" + case codes.DataLoss: + return "DATA_LOSS" + case codes.Unauthenticated: + return "UNAUTHENTICATED" + default: + return "STATUS_" + strconv.FormatInt(int64(c), 10) + } +} diff --git a/api/trace/api.go b/api/trace/api.go index 7fbdaa8b0..3f09a0a55 100644 --- a/api/trace/api.go +++ b/api/trace/api.go @@ -18,6 +18,8 @@ import ( "context" "time" + "google.golang.org/grpc/codes" + "github.com/open-telemetry/opentelemetry-go/api/core" "github.com/open-telemetry/opentelemetry-go/api/log" "github.com/open-telemetry/opentelemetry-go/api/scope" @@ -27,7 +29,7 @@ import ( type ( Tracer interface { - Start(context.Context, string, ...Option) (context.Context, Span) + Start(context.Context, string, ...SpanOption) (context.Context, Span) WithSpan( ctx context.Context, @@ -58,17 +60,29 @@ type ( Tracer() Tracer Finish() + + // IsRecordingEvents returns true is the span is active and recording events is enabled. + IsRecordingEvents() bool + + // SpancContext returns span context of the span. Return SpanContext is usable + // even after the span is finished. + SpanContext() core.SpanContext + + SetStatus(codes.Code) } Injector interface { Inject(core.SpanContext, tag.Map) } - Option struct { - attribute core.KeyValue - attributes []core.KeyValue - startTime time.Time - reference Reference + // SpanOption apply changes to SpanOptions. + SpanOption func(*SpanOptions) + + SpanOptions struct { + attributes []core.KeyValue + startTime time.Time + reference Reference + recordEvent bool } Reference struct { @@ -95,7 +109,7 @@ func SetGlobalTracer(t Tracer) { global.Store(t) } -func Start(ctx context.Context, name string, opts ...Option) (context.Context, Span) { +func Start(ctx context.Context, name string, opts ...SpanOption) (context.Context, Span) { return GlobalTracer().Start(ctx, name, opts...) } @@ -121,38 +135,38 @@ func Inject(ctx context.Context, injector Injector) { span.Tracer().Inject(ctx, span, injector) } -func WithStartTime(t time.Time) Option { - return Option{ - startTime: t, +func WithStartTime(t time.Time) SpanOption { + return func(o *SpanOptions) { + o.startTime = t } } -func WithAttributes(attrs ...core.KeyValue) Option { - return Option{ - attributes: attrs, +func WithAttributes(attrs ...core.KeyValue) SpanOption { + return func(o *SpanOptions) { + o.attributes = attrs } } -func WithAttribute(attr core.KeyValue) Option { - return Option{ - attribute: attr, +func WithRecordEvents() SpanOption { + return func(o *SpanOptions) { + o.recordEvent = true } } -func ChildOf(sc core.SpanContext) Option { - return Option{ - reference: Reference{ +func ChildOf(sc core.SpanContext) SpanOption { + return func(o *SpanOptions) { + o.reference = Reference{ SpanContext: sc, RelationshipType: ChildOfRelationship, - }, + } } } -func FollowsFrom(sc core.SpanContext) Option { - return Option{ - reference: Reference{ +func FollowsFrom(sc core.SpanContext) SpanOption { + return func(o *SpanOptions) { + o.reference = Reference{ SpanContext: sc, RelationshipType: FollowsFromRelationship, - }, + } } } diff --git a/api/trace/span.go b/api/trace/span.go index b0b7083d6..45546b9a8 100644 --- a/api/trace/span.go +++ b/api/trace/span.go @@ -17,12 +17,44 @@ package trace import ( "context" + "google.golang.org/grpc/codes" + "github.com/open-telemetry/opentelemetry-go/api/core" "github.com/open-telemetry/opentelemetry-go/api/log" "github.com/open-telemetry/opentelemetry-go/api/stats" "github.com/open-telemetry/opentelemetry-go/exporter/observer" ) +// SpancContext returns span context of the span. Return SpanContext is usable +// even after the span is finished. +func (sp *span) SpanContext() core.SpanContext { + if sp == nil { + return core.INVALID_SPAN_CONTEXT + } + return sp.spanContext +} + +// IsRecordingEvents returns true is the span is active and recording events is enabled. +func (sp *span) IsRecordingEvents() bool { + return false +} + +// SetStatus sets the status of the span. +func (sp *span) SetStatus(status codes.Code) { + if sp == nil { + return + } + sid := sp.ScopeID() + + observer.Record(observer.Event{ + Type: observer.SET_STATUS, + Scope: sid, + Sequence: sid.EventID, + Status: status, + }) + sp.status = status +} + func (sp *span) ScopeID() core.ScopeID { if sp == nil { return core.ScopeID{} diff --git a/api/trace/trace.go b/api/trace/trace.go index 597a314e9..aa4417eb8 100644 --- a/api/trace/trace.go +++ b/api/trace/trace.go @@ -19,7 +19,8 @@ import ( "math/rand" "sync" "sync/atomic" - "time" + + "google.golang.org/grpc/codes" "github.com/open-telemetry/opentelemetry-go/api/core" "github.com/open-telemetry/opentelemetry-go/api/log" @@ -35,6 +36,8 @@ type ( lock sync.Mutex eventID core.EventID finishOnce sync.Once + recordEvent bool + status codes.Code } tracer struct { @@ -93,34 +96,21 @@ func (t *tracer) WithSpan(ctx context.Context, name string, body func(context.Co return nil } -func (t *tracer) Start(ctx context.Context, name string, opts ...Option) (context.Context, Span) { +func (t *tracer) Start(ctx context.Context, name string, opts ...SpanOption) (context.Context, Span) { var child core.SpanContext child.SpanID = rand.Uint64() - var startTime time.Time - var attributes []core.KeyValue - var reference Reference + o := &SpanOptions{} for _, opt := range opts { - if !opt.startTime.IsZero() { - startTime = opt.startTime - } - if len(opt.attributes) != 0 { - attributes = append(opt.attributes, attributes...) - } - if opt.attribute.Key != nil { - attributes = append(attributes, opt.attribute) - } - if opt.reference.HasTraceID() { - reference = opt.reference - } + opt(o) } var parentScope core.ScopeID - if reference.HasTraceID() { - parentScope = reference.Scope() + if o.reference.HasTraceID() { + parentScope = o.reference.Scope() } else { parentScope = Active(ctx).ScopeID() } @@ -142,10 +132,11 @@ func (t *tracer) Start(ctx context.Context, name string, opts ...Option) (contex span := &span{ spanContext: child, tracer: t, + recordEvent: o.recordEvent, eventID: observer.Record(observer.Event{ - Time: startTime, + Time: o.startTime, Type: observer.START_SPAN, - Scope: scope.New(childScope, attributes...).ScopeID(), + Scope: scope.New(childScope, o.attributes...).ScopeID(), Context: ctx, Parent: parentScope, String: name, diff --git a/example/http/client/client.go b/example/http/client/client.go index 23306752e..172b57242 100644 --- a/example/http/client/client.go +++ b/example/http/client/client.go @@ -24,6 +24,8 @@ import ( "github.com/open-telemetry/opentelemetry-go/api/trace" "github.com/open-telemetry/opentelemetry-go/plugin/httptrace" + "google.golang.org/grpc/codes" + _ "github.com/open-telemetry/opentelemetry-go/exporter/loader" ) @@ -59,6 +61,7 @@ func main() { } body, err = ioutil.ReadAll(res.Body) res.Body.Close() + trace.Active(ctx).SetStatus(codes.OK) return err }) diff --git a/exporter/observer/observer.go b/exporter/observer/observer.go index cd4df24e7..2c5558357 100644 --- a/exporter/observer/observer.go +++ b/exporter/observer/observer.go @@ -20,6 +20,8 @@ import ( "sync/atomic" "time" + "google.golang.org/grpc/codes" + "github.com/open-telemetry/opentelemetry-go/api/core" ) @@ -43,6 +45,7 @@ type ( Mutators []core.Mutator // SET_ATTRIBUTES Arguments []interface{} // LOGF_EVENT Recovered interface{} // FINISH_SPAN + Status codes.Code // SET_STATUS // Values String string // START_SPAN, EVENT, ... @@ -72,6 +75,7 @@ const ( NEW_METRIC MODIFY_ATTR RECORD_STATS + SET_STATUS ) var ( diff --git a/exporter/reader/format/format.go b/exporter/reader/format/format.go index 8bf8f9c9e..2d924de71 100644 --- a/exporter/reader/format/format.go +++ b/exporter/reader/format/format.go @@ -92,6 +92,10 @@ func AppendEvent(buf *strings.Builder, data reader.Event) { }) buf.WriteString("}") } + case reader.SET_STATUS: + buf.WriteString("set status ") + buf.WriteString(core.GrpcCodeToString(data.Status)) + default: buf.WriteString(fmt.Sprintf("WAT? %d", data.Type)) } diff --git a/exporter/reader/reader.go b/exporter/reader/reader.go index db48a1ff7..0686524bc 100644 --- a/exporter/reader/reader.go +++ b/exporter/reader/reader.go @@ -19,6 +19,8 @@ import ( "sync" "time" + "google.golang.org/grpc/codes" + "github.com/open-telemetry/opentelemetry-go/api/core" "github.com/open-telemetry/opentelemetry-go/api/metric" "github.com/open-telemetry/opentelemetry-go/api/tag" @@ -49,6 +51,7 @@ type ( Duration time.Duration Name string Message string + Status codes.Code } Measurement struct { @@ -75,6 +78,7 @@ type ( start time.Time startTags tag.Map spanContext core.SpanContext + status codes.Code *readerScope } @@ -106,6 +110,7 @@ const ( LOGF_EVENT MODIFY_ATTR RECORD_STATS + SET_STATUS ) // NewReaderObserver returns an implementation that computes the @@ -291,6 +296,15 @@ func (ro *readerObserver) Observe(event observer.Event) { ro.addMeasurement(&read, event.Stat) } + case observer.SET_STATUS: + read.Type = SET_STATUS + read.Status = event.Status + _, span := ro.readScope(event.Scope) + if span != nil { + span.status = event.Status + read.SpanContext = span.spanContext + } + default: panic(fmt.Sprint("Unhandled case: ", event.Type)) } diff --git a/go.mod b/go.mod index 2ff6b9720..c7f5965d4 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,5 @@ require ( github.com/onsi/ginkgo v1.8.0 // indirect github.com/onsi/gomega v1.5.0 // indirect golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd + google.golang.org/grpc v1.21.1 ) diff --git a/go.sum b/go.sum index 884cd3c59..6833a5db3 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,18 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2 h1:HTOmFEEYrWi4MW5ZKUx6xfeyM10Sx3kQF65xiQJMPYA= github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 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/fatih/color v1.6.0 h1:66qjqZk8kalYAvDRtM1AdAJQI0tj4Wrue3Eq3B3pmFU= github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-critic/go-critic v0.0.0-20181204210945-1df300866540 h1:7CU1IXBpPvxpQ/NqJrpuMXMHAw+FB2vfqtRF8tgW9fw= github.com/go-critic/go-critic v0.0.0-20181204210945-1df300866540/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= @@ -43,9 +48,14 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.0.0 h1:HzcpUG60pfl43n9d2qbdi/3l1uKpAmxlfWEPWtV/QxM= github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= @@ -83,6 +93,7 @@ github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSW github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno= @@ -170,15 +181,22 @@ github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/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 h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= @@ -186,11 +204,15 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -198,10 +220,16 @@ golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd h1:7E3PabyysDSEjnaANKBgums/hyvMI/HoHQ50qZEzTrg= golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= @@ -218,6 +246,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=