diff --git a/vendor/github.com/opentracing/opentracing-go/LICENSE b/vendor/github.com/opentracing/opentracing-go/LICENSE index 148509a40..f0027349e 100644 --- a/vendor/github.com/opentracing/opentracing-go/LICENSE +++ b/vendor/github.com/opentracing/opentracing-go/LICENSE @@ -1,21 +1,201 @@ -The MIT License (MIT) + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Copyright (c) 2016 The OpenTracing Authors + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 1. Definitions. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 The OpenTracing Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/opentracing/opentracing-go/ext/tags.go b/vendor/github.com/opentracing/opentracing-go/ext/tags.go index 09f647b5a..8800129a2 100644 --- a/vendor/github.com/opentracing/opentracing-go/ext/tags.go +++ b/vendor/github.com/opentracing/opentracing-go/ext/tags.go @@ -15,7 +15,7 @@ import opentracing "github.com/opentracing/opentracing-go" // var ( ////////////////////////////////////////////////////////////////////// - // SpanKind (client/server) + // SpanKind (client/server or producer/consumer) ////////////////////////////////////////////////////////////////////// // SpanKind hints at relationship between spans, e.g. client/server @@ -31,6 +31,16 @@ var ( SpanKindRPCServerEnum = SpanKindEnum("server") SpanKindRPCServer = opentracing.Tag{Key: string(SpanKind), Value: SpanKindRPCServerEnum} + // SpanKindProducer marks a span representing the producer-side of a + // message bus + SpanKindProducerEnum = SpanKindEnum("producer") + SpanKindProducer = opentracing.Tag{Key: string(SpanKind), Value: SpanKindProducerEnum} + + // SpanKindConsumer marks a span representing the consumer-side of a + // message bus + SpanKindConsumerEnum = SpanKindEnum("consumer") + SpanKindConsumer = opentracing.Tag{Key: string(SpanKind), Value: SpanKindConsumerEnum} + ////////////////////////////////////////////////////////////////////// // Component name ////////////////////////////////////////////////////////////////////// @@ -52,14 +62,19 @@ var ( // communications, like an RPC call. ////////////////////////////////////////////////////////////////////// - // PeerService records the service name of the peer + // PeerService records the service name of the peer. PeerService = stringTagName("peer.service") + // PeerAddress records the address name of the peer. This may be a "ip:port", + // a bare "hostname", a FQDN or even a database DSN substring + // like "mysql://username@127.0.0.1:3306/dbname" + PeerAddress = stringTagName("peer.address") + // PeerHostname records the host name of the peer PeerHostname = stringTagName("peer.hostname") // PeerHostIPv4 records IP v4 host address of the peer - PeerHostIPv4 = uint32TagName("peer.ipv4") + PeerHostIPv4 = ipv4Tag("peer.ipv4") // PeerHostIPv6 records IP v6 host address of the peer PeerHostIPv6 = stringTagName("peer.ipv6") @@ -82,6 +97,31 @@ var ( // HTTP response. HTTPStatusCode = uint16TagName("http.status_code") + ////////////////////////////////////////////////////////////////////// + // DB Tags + ////////////////////////////////////////////////////////////////////// + + // DBInstance is database instance name. + DBInstance = stringTagName("db.instance") + + // DBStatement is a database statement for the given database type. + // It can be a query or a prepared statement (i.e., before substitution). + DBStatement = stringTagName("db.statement") + + // DBType is a database type. For any SQL database, "sql". + // For others, the lower-case database category, e.g. "redis" + DBType = stringTagName("db.type") + + // DBUser is a username for accessing database. + DBUser = stringTagName("db.user") + + ////////////////////////////////////////////////////////////////////// + // Message Bus Tag + ////////////////////////////////////////////////////////////////////// + + // MessageBusDestination is an address at which messages can be exchanged + MessageBusDestination = stringTagName("message_bus.destination") + ////////////////////////////////////////////////////////////////////// // Error Tag ////////////////////////////////////////////////////////////////////// @@ -156,3 +196,15 @@ type boolTagName string func (tag boolTagName) Set(span opentracing.Span, value bool) { span.SetTag(string(tag), value) } + +type ipv4Tag string + +// Set adds IP v4 host address of the peer as an uint32 value to the `span`, keep this for backward and zipkin compatibility +func (tag ipv4Tag) Set(span opentracing.Span, value uint32) { + span.SetTag(string(tag), value) +} + +// SetString records IP v4 host address of the peer as a .-separated tuple to the `span`. E.g., "127.0.0.1" +func (tag ipv4Tag) SetString(span opentracing.Span, value string) { + span.SetTag(string(tag), value) +} diff --git a/vendor/github.com/opentracing/opentracing-go/globaltracer.go b/vendor/github.com/opentracing/opentracing-go/globaltracer.go index 2df34c9b1..8c8e793ff 100644 --- a/vendor/github.com/opentracing/opentracing-go/globaltracer.go +++ b/vendor/github.com/opentracing/opentracing-go/globaltracer.go @@ -4,18 +4,18 @@ var ( globalTracer Tracer = NoopTracer{} ) -// InitGlobalTracer sets the [singleton] opentracing.Tracer returned by +// SetGlobalTracer sets the [singleton] opentracing.Tracer returned by // GlobalTracer(). Those who use GlobalTracer (rather than directly manage an -// opentracing.Tracer instance) should call InitGlobalTracer as early as +// opentracing.Tracer instance) should call SetGlobalTracer as early as // possible in main(), prior to calling the `StartSpan` global func below. -// Prior to calling `InitGlobalTracer`, any Spans started via the `StartSpan` +// Prior to calling `SetGlobalTracer`, any Spans started via the `StartSpan` // (etc) globals are noops. -func InitGlobalTracer(tracer Tracer) { +func SetGlobalTracer(tracer Tracer) { globalTracer = tracer } // GlobalTracer returns the global singleton `Tracer` implementation. -// Before `InitGlobalTracer()` is called, the `GlobalTracer()` is a noop +// Before `SetGlobalTracer()` is called, the `GlobalTracer()` is a noop // implementation that drops all data handed to it. func GlobalTracer() Tracer { return globalTracer @@ -25,3 +25,8 @@ func GlobalTracer() Tracer { func StartSpan(operationName string, opts ...StartSpanOption) Span { return globalTracer.StartSpan(operationName, opts...) } + +// InitGlobalTracer is deprecated. Please use SetGlobalTracer. +func InitGlobalTracer(tracer Tracer) { + SetGlobalTracer(tracer) +} diff --git a/vendor/github.com/opentracing/opentracing-go/gocontext.go b/vendor/github.com/opentracing/opentracing-go/gocontext.go index 222a65202..05a62e70b 100644 --- a/vendor/github.com/opentracing/opentracing-go/gocontext.go +++ b/vendor/github.com/opentracing/opentracing-go/gocontext.go @@ -1,6 +1,6 @@ package opentracing -import "golang.org/x/net/context" +import "context" type contextKey struct{} @@ -46,12 +46,9 @@ func StartSpanFromContext(ctx context.Context, operationName string, opts ...Sta // startSpanFromContextWithTracer is factored out for testing purposes. func startSpanFromContextWithTracer(ctx context.Context, tracer Tracer, operationName string, opts ...StartSpanOption) (Span, context.Context) { - var span Span if parentSpan := SpanFromContext(ctx); parentSpan != nil { opts = append(opts, ChildOf(parentSpan.Context())) - span = tracer.StartSpan(operationName, opts...) - } else { - span = tracer.StartSpan(operationName, opts...) } + span := tracer.StartSpan(operationName, opts...) return span, ContextWithSpan(ctx, span) } diff --git a/vendor/github.com/opentracing/opentracing-go/harness/api_checkers.go b/vendor/github.com/opentracing/opentracing-go/harness/api_checkers.go new file mode 100644 index 000000000..ce7950bc7 --- /dev/null +++ b/vendor/github.com/opentracing/opentracing-go/harness/api_checkers.go @@ -0,0 +1,472 @@ +/* + +Package harness provides a suite of API compatibility checks. They were originally ported from the +OpenTracing Python library's "harness" module. + +To run this test suite against your tracer, call harness.RunAPIChecks and provide it a function +that returns a Tracer implementation and a function to call to close it. The function will be +called to create a new tracer before each test in the suite is run, and the returned closer function +will be called after each test is finished. + +Several options provide additional checks for your Tracer's behavior: CheckBaggageValues(true) +indicates your tracer supports baggage propagation, CheckExtract(true) tells the suite to test if +the Tracer can extract a trace context from text and binary carriers, and CheckInject(true) tests +if the Tracer can inject the trace context into a carrier. + +The UseProbe option provides an APICheckProbe implementation that allows the test suite to +additionally check if two Spans are part of the same trace, and if a Span and a SpanContext +are part of the same trace. Implementing an APICheckProbe provides additional assertions that +your tracer is working properly. + +*/ +package harness + +import ( + "bytes" + "testing" + "time" + + opentracing "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/log" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +// APICheckCapabilities describes capabilities of a Tracer that should be checked by APICheckSuite. +type APICheckCapabilities struct { + CheckBaggageValues bool // whether to check for propagation of baggage values + CheckExtract bool // whether to check if extracting contexts from carriers works + CheckInject bool // whether to check if injecting contexts works + Probe APICheckProbe // optional interface providing methods to check recorded data +} + +// APICheckProbe exposes methods for testing data recorded by a Tracer. +type APICheckProbe interface { + // SameTrace helps tests assert that this tracer's spans are from the same trace. + SameTrace(first, second opentracing.Span) bool + // SameSpanContext helps tests assert that a span and a context are from the same trace and span. + SameSpanContext(opentracing.Span, opentracing.SpanContext) bool +} + +// APICheckSuite is a testify suite for checking a Tracer against the OpenTracing API. +type APICheckSuite struct { + suite.Suite + opts APICheckCapabilities + newTracer func() (tracer opentracing.Tracer, closer func()) + tracer opentracing.Tracer + closer func() +} + +// RunAPIChecks runs a test suite to check a Tracer against the OpenTracing API. +// It is provided a function that will be executed to create and destroy a tracer for each test +// in the suite, and the given APICheckOption functional options `opts`. +func RunAPIChecks( + t *testing.T, + newTracer func() (tracer opentracing.Tracer, closer func()), + opts ...APICheckOption, +) { + s := &APICheckSuite{newTracer: newTracer} + for _, opt := range opts { + opt(s) + } + suite.Run(t, s) +} + +// APICheckOption instances may be passed to NewAPICheckSuite. +type APICheckOption func(*APICheckSuite) + +// CheckBaggageValues returns an option that sets whether to check for propagation of baggage values. +func CheckBaggageValues(val bool) APICheckOption { + return func(s *APICheckSuite) { + s.opts.CheckBaggageValues = val + } +} + +// CheckExtract returns an option that sets whether to check if extracting contexts from carriers works. +func CheckExtract(val bool) APICheckOption { + return func(s *APICheckSuite) { + s.opts.CheckExtract = val + } +} + +// CheckInject returns an option that sets whether to check if injecting contexts works. +func CheckInject(val bool) APICheckOption { + return func(s *APICheckSuite) { + s.opts.CheckInject = val + } +} + +// CheckEverything returns an option that enables all API checks. +func CheckEverything() APICheckOption { + return func(s *APICheckSuite) { + s.opts.CheckBaggageValues = true + s.opts.CheckExtract = true + s.opts.CheckInject = true + } +} + +// UseProbe returns an option that specifies an APICheckProbe implementation to use. +func UseProbe(probe APICheckProbe) APICheckOption { + return func(s *APICheckSuite) { + s.opts.Probe = probe + } +} + +// SetupTest creates a tracer for this specific test invocation. +func (s *APICheckSuite) SetupTest() { + s.tracer, s.closer = s.newTracer() + if s.tracer == nil { + s.T().Fatalf("newTracer returned nil Tracer") + } +} + +// TearDownTest closes the tracer, and clears the test-specific tracer. +func (s *APICheckSuite) TearDownTest() { + if s.closer != nil { + s.closer() + } + s.tracer, s.closer = nil, nil +} + +// TestStartSpan checks if a Tracer can start a span and calls some span API methods. +func (s *APICheckSuite) TestStartSpan() { + span := s.tracer.StartSpan( + "Fry", + opentracing.Tag{Key: "birthday", Value: "August 14 1974"}) + span.LogFields( + log.String("hospital", "Brooklyn Pre-Med Hospital"), + log.String("city", "Old New York")) + span.Finish() +} + +// TestStartSpanWithParent checks if a Tracer can start a span with a specified parent. +func (s *APICheckSuite) TestStartSpanWithParent() { + parentSpan := s.tracer.StartSpan("Turanga Munda") + s.NotNil(parentSpan) + + childFns := []func(opentracing.SpanContext) opentracing.SpanReference{ + opentracing.ChildOf, + opentracing.FollowsFrom, + } + for _, childFn := range childFns { + span := s.tracer.StartSpan( + "Leela", + childFn(parentSpan.Context()), + opentracing.Tag{Key: "birthplace", Value: "sewers"}) + span.Finish() + if s.opts.Probe != nil { + s.True(s.opts.Probe.SameTrace(parentSpan, span)) + } else { + s.T().Log("harness.Probe not specified, skipping") + } + } + + parentSpan.Finish() +} + +// TestSetOperationName attempts to set the operation name on a span after it has been created. +func (s *APICheckSuite) TestSetOperationName() { + span := s.tracer.StartSpan("").SetOperationName("Farnsworth") + span.Finish() +} + +// TestSpanTagValueTypes sets tags using values of different types. +func (s *APICheckSuite) TestSpanTagValueTypes() { + span := s.tracer.StartSpan("ManyTypes") + span. + SetTag("an_int", 9). + SetTag("a_bool", true). + SetTag("a_string", "aoeuidhtns") +} + +// TestSpanTagsWithChaining tests chaining of calls to SetTag. +func (s *APICheckSuite) TestSpanTagsWithChaining() { + span := s.tracer.StartSpan("Farnsworth") + span. + SetTag("birthday", "9 April, 2841"). + SetTag("loves", "different lengths of wires") + span. + SetTag("unicode_val", "non-ascii: \u200b"). + SetTag("unicode_key_\u200b", "ascii val") + span.Finish() +} + +// TestSpanLogs tests calls to log keys and values with spans. +func (s *APICheckSuite) TestSpanLogs() { + span := s.tracer.StartSpan("Fry") + span.LogKV( + "event", "frozen", + "year", 1999, + "place", "Cryogenics Labs") + span.LogKV( + "event", "defrosted", + "year", 2999, + "place", "Cryogenics Labs") + + ts := time.Now() + span.FinishWithOptions(opentracing.FinishOptions{ + LogRecords: []opentracing.LogRecord{ + { + Timestamp: ts, + Fields: []log.Field{ + log.String("event", "job-assignment"), + log.String("type", "delivery boy"), + }, + }, + }}) + + // Test deprecated log methods + span.LogEvent("an arbitrary event") + span.LogEventWithPayload("y", "z") + span.Log(opentracing.LogData{Event: "y", Payload: "z"}) +} + +func assertEmptyBaggage(t *testing.T, spanContext opentracing.SpanContext) { + if !assert.NotNil(t, spanContext, "assertEmptyBaggage got empty context") { + return + } + spanContext.ForeachBaggageItem(func(k, v string) bool { + assert.Fail(t, "new span shouldn't have baggage") + return false + }) +} + +// TestSpanBaggage tests calls to set and get span baggage, and if the CheckBaggageValues option +// is set, asserts that baggage values were successfully retrieved. +func (s *APICheckSuite) TestSpanBaggage() { + span := s.tracer.StartSpan("Fry") + assertEmptyBaggage(s.T(), span.Context()) + + spanRef := span.SetBaggageItem("Kiff-loves", "Amy") + s.Exactly(spanRef, span) + + val := span.BaggageItem("Kiff-loves") + if s.opts.CheckBaggageValues { + s.Equal("Amy", val) + } else { + s.T().Log("CheckBaggageValues capability not set, skipping") + } + span.Finish() +} + +// TestContextBaggage tests calls to set and get span baggage, and if the CheckBaggageValues option +// is set, asserts that baggage values were successfully retrieved from the span's SpanContext. +func (s *APICheckSuite) TestContextBaggage() { + span := s.tracer.StartSpan("Fry") + assertEmptyBaggage(s.T(), span.Context()) + + span.SetBaggageItem("Kiff-loves", "Amy") + if s.opts.CheckBaggageValues { + called := false + span.Context().ForeachBaggageItem(func(k, v string) bool { + s.False(called) + called = true + s.Equal("Kiff-loves", k) + s.Equal("Amy", v) + return true + }) + } else { + s.T().Log("CheckBaggageValues capability not set, skipping") + } + span.Finish() +} + +// TestTextPropagation tests if the Tracer can Inject a span into a TextMapCarrier, and later Extract it. +// If CheckExtract is set, it will check if Extract was successful (returned no error). If a Probe is set, +// it will check if the extracted context is in the same trace as the original span. +func (s *APICheckSuite) TestTextPropagation() { + span := s.tracer.StartSpan("Bender") + textCarrier := opentracing.TextMapCarrier{} + err := span.Tracer().Inject(span.Context(), opentracing.TextMap, textCarrier) + assert.NoError(s.T(), err) + + extractedContext, err := s.tracer.Extract(opentracing.TextMap, textCarrier) + if s.opts.CheckExtract { + s.NoError(err) + assertEmptyBaggage(s.T(), extractedContext) + } else { + s.T().Log("CheckExtract capability not set, skipping") + } + if s.opts.Probe != nil { + s.True(s.opts.Probe.SameSpanContext(span, extractedContext)) + } else { + s.T().Log("harness.Probe not specified, skipping") + } + span.Finish() +} + +// TestHTTPPropagation tests if the Tracer can Inject a span into HTTP headers, and later Extract it. +// If CheckExtract is set, it will check if Extract was successful (returned no error). If a Probe is set, +// it will check if the extracted context is in the same trace as the original span. +func (s *APICheckSuite) TestHTTPPropagation() { + span := s.tracer.StartSpan("Bender") + textCarrier := opentracing.HTTPHeadersCarrier{} + err := span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, textCarrier) + s.NoError(err) + + extractedContext, err := s.tracer.Extract(opentracing.HTTPHeaders, textCarrier) + if s.opts.CheckExtract { + s.NoError(err) + assertEmptyBaggage(s.T(), extractedContext) + } else { + s.T().Log("CheckExtract capability not set, skipping") + } + if s.opts.Probe != nil { + s.True(s.opts.Probe.SameSpanContext(span, extractedContext)) + } else { + s.T().Log("harness.Probe not specified, skipping") + } + span.Finish() +} + +// TestBinaryPropagation tests if the Tracer can Inject a span into a binary buffer, and later Extract it. +// If CheckExtract is set, it will check if Extract was successful (returned no error). If a Probe is set, +// it will check if the extracted context is in the same trace as the original span. +func (s *APICheckSuite) TestBinaryPropagation() { + span := s.tracer.StartSpan("Bender") + buf := new(bytes.Buffer) + err := span.Tracer().Inject(span.Context(), opentracing.Binary, buf) + s.NoError(err) + + extractedContext, err := s.tracer.Extract(opentracing.Binary, buf) + if s.opts.CheckExtract { + s.NoError(err) + assertEmptyBaggage(s.T(), extractedContext) + } else { + s.T().Log("CheckExtract capability not set, skipping") + } + if s.opts.Probe != nil { + s.True(s.opts.Probe.SameSpanContext(span, extractedContext)) + } else { + s.T().Log("harness.Probe not specified, skipping") + } + span.Finish() +} + +// TestMandatoryFormats tests if all mandatory carrier formats are supported. If CheckExtract is set, it +// will check if the call to Extract was successful (returned no error such as ErrUnsupportedFormat). +func (s *APICheckSuite) TestMandatoryFormats() { + formats := []struct{ Format, Carrier interface{} }{ + {opentracing.TextMap, opentracing.TextMapCarrier{}}, + {opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier{}}, + {opentracing.Binary, new(bytes.Buffer)}, + } + span := s.tracer.StartSpan("Bender") + for _, fmtCarrier := range formats { + err := span.Tracer().Inject(span.Context(), fmtCarrier.Format, fmtCarrier.Carrier) + s.NoError(err) + spanCtx, err := s.tracer.Extract(fmtCarrier.Format, fmtCarrier.Carrier) + if s.opts.CheckExtract { + s.NoError(err) + assertEmptyBaggage(s.T(), spanCtx) + } else { + s.T().Log("CheckExtract capability not set, skipping") + } + } +} + +// TestUnknownFormat checks if attempting to Inject or Extract using an unsupported format +// returns ErrUnsupportedFormat, if CheckInject and CheckExtract are set. +func (s *APICheckSuite) TestUnknownFormat() { + customFormat := "kiss my shiny metal ..." + span := s.tracer.StartSpan("Bender") + + err := span.Tracer().Inject(span.Context(), customFormat, nil) + if s.opts.CheckInject { + s.Equal(opentracing.ErrUnsupportedFormat, err) + } else { + s.T().Log("CheckInject capability not set, skipping") + } + ctx, err := s.tracer.Extract(customFormat, nil) + s.Nil(ctx) + if s.opts.CheckExtract { + s.Equal(opentracing.ErrUnsupportedFormat, err) + } else { + s.T().Log("CheckExtract capability not set, skipping") + } +} + +// ForeignSpanContext satisfies the opentracing.SpanContext interface, but otherwise does nothing. +type ForeignSpanContext struct{} + +// ForeachBaggageItem could call handler for each baggage KV, but does nothing. +func (f ForeignSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {} + +// NotACarrier does not satisfy any of the opentracing carrier interfaces. +type NotACarrier struct{} + +// TestInvalidInject checks if errors are returned when Inject is called with invalid inputs. +func (s *APICheckSuite) TestInvalidInject() { + if !s.opts.CheckInject { + s.T().Skip("CheckInject capability not set, skipping") + } + span := s.tracer.StartSpan("op") + + // binary inject + err := span.Tracer().Inject(ForeignSpanContext{}, opentracing.Binary, new(bytes.Buffer)) + s.Equal(opentracing.ErrInvalidSpanContext, err, "Foreign SpanContext should return invalid error") + err = span.Tracer().Inject(span.Context(), opentracing.Binary, NotACarrier{}) + s.Equal(opentracing.ErrInvalidCarrier, err, "Carrier that's not io.Writer should return error") + + // text inject + err = span.Tracer().Inject(ForeignSpanContext{}, opentracing.TextMap, opentracing.TextMapCarrier{}) + s.Equal(opentracing.ErrInvalidSpanContext, err, "Foreign SpanContext should return invalid error") + err = span.Tracer().Inject(span.Context(), opentracing.TextMap, NotACarrier{}) + s.Equal(opentracing.ErrInvalidCarrier, err, "Carrier that's not TextMapWriter should return error") + + // HTTP inject + err = span.Tracer().Inject(ForeignSpanContext{}, opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier{}) + s.Equal(opentracing.ErrInvalidSpanContext, err, "Foreign SpanContext should return invalid error") + err = span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, NotACarrier{}) + s.Equal(opentracing.ErrInvalidCarrier, err, "Carrier that's not TextMapWriter should return error") +} + +// TestInvalidExtract checks if errors are returned when Extract is called with invalid inputs. +func (s *APICheckSuite) TestInvalidExtract() { + if !s.opts.CheckExtract { + s.T().Skip("CheckExtract capability not set, skipping") + } + span := s.tracer.StartSpan("op") + + // binary extract + ctx, err := span.Tracer().Extract(opentracing.Binary, NotACarrier{}) + s.Equal(opentracing.ErrInvalidCarrier, err, "Carrier that's not io.Reader should return error") + s.Nil(ctx) + + // text extract + ctx, err = span.Tracer().Extract(opentracing.TextMap, NotACarrier{}) + s.Equal(opentracing.ErrInvalidCarrier, err, "Carrier that's not TextMapReader should return error") + s.Nil(ctx) + + // HTTP extract + ctx, err = span.Tracer().Extract(opentracing.HTTPHeaders, NotACarrier{}) + s.Equal(opentracing.ErrInvalidCarrier, err, "Carrier that's not TextMapReader should return error") + s.Nil(ctx) + + span.Finish() +} + +// TestMultiBaggage tests calls to set multiple baggage items, and if the CheckBaggageValues option +// is set, asserts that a baggage value was successfully retrieved from the span's SpanContext. +// It also ensures that returning false from the ForeachBaggageItem handler aborts iteration. +func (s *APICheckSuite) TestMultiBaggage() { + span := s.tracer.StartSpan("op") + assertEmptyBaggage(s.T(), span.Context()) + + span.SetBaggageItem("Bag1", "BaggageVal1") + span.SetBaggageItem("Bag2", "BaggageVal2") + if s.opts.CheckBaggageValues { + s.Equal("BaggageVal1", span.BaggageItem("Bag1")) + s.Equal("BaggageVal2", span.BaggageItem("Bag2")) + called := false + span.Context().ForeachBaggageItem(func(k, v string) bool { + s.False(called) // should only be called once + called = true + return false + }) + s.True(called) + } else { + s.T().Log("CheckBaggageValues capability not set, skipping") + } + span.Finish() +} diff --git a/vendor/github.com/opentracing/opentracing-go/log/field.go b/vendor/github.com/opentracing/opentracing-go/log/field.go index 5bc47b644..50feea341 100644 --- a/vendor/github.com/opentracing/opentracing-go/log/field.go +++ b/vendor/github.com/opentracing/opentracing-go/log/field.go @@ -20,6 +20,7 @@ const ( errorType objectType lazyLoggerType + noopType ) // Field instances are constructed via LogBool, LogString, and so on. @@ -152,6 +153,25 @@ func Lazy(ll LazyLogger) Field { } } +// Noop creates a no-op log field that should be ignored by the tracer. +// It can be used to capture optional fields, for example those that should +// only be logged in non-production environment: +// +// func customerField(order *Order) log.Field { +// if os.Getenv("ENVIRONMENT") == "dev" { +// return log.String("customer", order.Customer.ID) +// } +// return log.Noop() +// } +// +// span.LogFields(log.String("event", "purchase"), customerField(order)) +// +func Noop() Field { + return Field{ + fieldType: noopType, + } +} + // Encoder allows access to the contents of a Field (via a call to // Field.Marshal). // @@ -194,11 +214,17 @@ func (lf Field) Marshal(visitor Encoder) { case float64Type: visitor.EmitFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal))) case errorType: - visitor.EmitString(lf.key, lf.interfaceVal.(error).Error()) + if err, ok := lf.interfaceVal.(error); ok { + visitor.EmitString(lf.key, err.Error()) + } else { + visitor.EmitString(lf.key, "") + } case objectType: visitor.EmitObject(lf.key, lf.interfaceVal) case lazyLoggerType: visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger)) + case noopType: + // intentionally left blank } } @@ -230,6 +256,8 @@ func (lf Field) Value() interface{} { return math.Float64frombits(uint64(lf.numericVal)) case errorType, objectType, lazyLoggerType: return lf.interfaceVal + case noopType: + return nil default: return nil } diff --git a/vendor/github.com/opentracing/opentracing-go/mocktracer/mockspan.go b/vendor/github.com/opentracing/opentracing-go/mocktracer/mockspan.go index 5ca711485..8c7932ce6 100644 --- a/vendor/github.com/opentracing/opentracing-go/mocktracer/mockspan.go +++ b/vendor/github.com/opentracing/opentracing-go/mocktracer/mockspan.go @@ -28,8 +28,7 @@ type MockSpanContext struct { var mockIDSource = uint32(42) func nextMockID() int { - atomic.AddUint32(&mockIDSource, 1) - return int(atomic.LoadUint32(&mockIDSource)) + return int(atomic.AddUint32(&mockIDSource, 1)) } // ForeachBaggageItem belongs to the SpanContext interface @@ -136,6 +135,8 @@ func (s *MockSpan) Logs() []MockLogRecord { // Context belongs to the Span interface func (s *MockSpan) Context() opentracing.SpanContext { + s.Lock() + defer s.Unlock() return s.SpanContext } diff --git a/vendor/github.com/opentracing/opentracing-go/noop.go b/vendor/github.com/opentracing/opentracing-go/noop.go index bd559dc8d..0d32f692c 100644 --- a/vendor/github.com/opentracing/opentracing-go/noop.go +++ b/vendor/github.com/opentracing/opentracing-go/noop.go @@ -2,8 +2,19 @@ package opentracing import "github.com/opentracing/opentracing-go/log" -// A NoopTracer is a trivial implementation of Tracer for which all operations -// are no-ops. +// A NoopTracer is a trivial, minimum overhead implementation of Tracer +// for which all operations are no-ops. +// +// The primary use of this implementation is in libraries, such as RPC +// frameworks, that make tracing an optional feature controlled by the +// end user. A no-op implementation allows said libraries to use it +// as the default Tracer and to write instrumentation that does +// not need to keep checking if the tracer instance is nil. +// +// For the same reason, the NoopTracer is the default "global" tracer +// (see GlobalTracer and SetGlobalTracer functions). +// +// WARNING: NoopTracer does not support baggage propagation. type NoopTracer struct{} type noopSpan struct{} diff --git a/vendor/github.com/opentracing/opentracing-go/propagation.go b/vendor/github.com/opentracing/opentracing-go/propagation.go index 9583fc53a..0dd466a37 100644 --- a/vendor/github.com/opentracing/opentracing-go/propagation.go +++ b/vendor/github.com/opentracing/opentracing-go/propagation.go @@ -72,18 +72,18 @@ const ( // // For Tracer.Extract(): the carrier must be a `TextMapReader`. // - // See HTTPHeaderCarrier for an implementation of both TextMapWriter + // See HTTPHeadersCarrier for an implementation of both TextMapWriter // and TextMapReader that defers to an http.Header instance for storage. // For example, Inject(): // // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) // err := span.Tracer().Inject( - // span, opentracing.HTTPHeaders, carrier) + // span.Context(), opentracing.HTTPHeaders, carrier) // // Or Extract(): // // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) - // span, err := tracer.Extract( + // clientContext, err := tracer.Extract( // opentracing.HTTPHeaders, carrier) // HTTPHeaders @@ -144,15 +144,15 @@ func (c TextMapCarrier) Set(key, val string) { // // Example usage for server side: // -// carrier := opentracing.HttpHeadersCarrier(httpReq.Header) -// spanContext, err := tracer.Extract(opentracing.HttpHeaders, carrier) +// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) +// clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier) // // Example usage for client side: // // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) // err := tracer.Inject( // span.Context(), -// opentracing.HttpHeaders, +// opentracing.HTTPHeaders, // carrier) // type HTTPHeadersCarrier http.Header diff --git a/vendor/github.com/opentracing/opentracing-go/span.go b/vendor/github.com/opentracing/opentracing-go/span.go index f6c3234ac..0d3fb5341 100644 --- a/vendor/github.com/opentracing/opentracing-go/span.go +++ b/vendor/github.com/opentracing/opentracing-go/span.go @@ -41,6 +41,8 @@ type Span interface { Context() SpanContext // Sets or changes the operation name. + // + // Returns a reference to this Span for chaining. SetOperationName(operationName string) Span // Adds a tag to the span. @@ -51,6 +53,8 @@ type Span interface { // other tag value types is undefined at the OpenTracing level. If a // tracing system does not know how to handle a particular value type, it // may ignore the tag, but shall not panic. + // + // Returns a reference to this Span for chaining. SetTag(key string, value interface{}) Span // LogFields is an efficient and type-checked way to record key:value diff --git a/vendor/github.com/opentracing/opentracing-go/tracer.go b/vendor/github.com/opentracing/opentracing-go/tracer.go index c84c4fdc4..7bca1f736 100644 --- a/vendor/github.com/opentracing/opentracing-go/tracer.go +++ b/vendor/github.com/opentracing/opentracing-go/tracer.go @@ -30,7 +30,7 @@ type Tracer interface { // sp := tracer.StartSpan( // "GetFeed", // opentracing.ChildOf(parentSpan.Context()), - // opentracing.Tag("user_agent", loggedReq.UserAgent), + // opentracing.Tag{"user_agent", loggedReq.UserAgent}, // opentracing.StartTime(loggedReq.Timestamp), // ) // @@ -52,7 +52,7 @@ type Tracer interface { // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) // err := tracer.Inject( // span.Context(), - // opentracing.HttpHeaders, + // opentracing.HTTPHeaders, // carrier) // // NOTE: All opentracing.Tracer implementations MUST support all @@ -80,8 +80,8 @@ type Tracer interface { // Example usage (with StartSpan): // // - // carrier := opentracing.HttpHeadersCarrier(httpReq.Header) - // clientContext, err := tracer.Extract(opentracing.HttpHeaders, carrier) + // carrier := opentracing.HTTPHeadersCarrier(httpReq.Header) + // clientContext, err := tracer.Extract(opentracing.HTTPHeaders, carrier) // // // ... assuming the ultimate goal here is to resume the trace with a // // server-side Span: diff --git a/vendor/manifest b/vendor/manifest index 2309f7138..d03d440d3 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -1655,7 +1655,7 @@ "importpath": "github.com/opentracing/opentracing-go", "repository": "https://github.com/opentracing/opentracing-go", "vcs": "git", - "revision": "902ca977fd85455c364050f985eba376b44315f0", + "revision": "bd9c3193394760d98b2fa6ebb2291f0cd1d06a7d", "branch": "master", "notests": true },