Updates for jaeger tracing client.

This commit is contained in:
Tristan Colgate-McFarlane 2018-08-01 12:52:03 +01:00 committed by Traefiker Bot
parent 4809476c19
commit 6f6ebb8025
92 changed files with 6824 additions and 819 deletions

19
Gopkg.lock generated
View file

@ -1213,23 +1213,30 @@
packages = [ packages = [
".", ".",
"config", "config",
"internal/baggage",
"internal/baggage/remote",
"internal/spanlog", "internal/spanlog",
"internal/throttler",
"internal/throttler/remote",
"log", "log",
"rpcmetrics", "rpcmetrics",
"thrift",
"thrift-gen/agent", "thrift-gen/agent",
"thrift-gen/baggage",
"thrift-gen/jaeger", "thrift-gen/jaeger",
"thrift-gen/sampling", "thrift-gen/sampling",
"thrift-gen/zipkincore", "thrift-gen/zipkincore",
"utils" "utils",
"zipkin"
] ]
revision = "3e3870040def0ebdaf65a003863fa64f5cb26139" revision = "b043381d944715b469fd6b37addfd30145ca1758"
version = "v2.9.0" version = "v2.14.0"
[[projects]] [[projects]]
name = "github.com/uber/jaeger-lib" name = "github.com/uber/jaeger-lib"
packages = ["metrics"] packages = ["metrics"]
revision = "3b2a9ad2a045881ab7a0f81d465be54c8292ee4f" revision = "ed3a127ec5fef7ae9ea95b01b542c47fbd999ce5"
version = "v1.1.0" version = "v1.5.0"
[[projects]] [[projects]]
name = "github.com/ugorji/go" name = "github.com/ugorji/go"
@ -1762,6 +1769,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "2b7ffb1d01d8a14224fcc9964900fb5a39fbf38cfacba45f49b931136e4fee9b" inputs-digest = "f323b06b4963d6cec0eee5b88dd4e85d6b2e80ea41418154a8a57a0dae574bcd"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View file

@ -162,11 +162,11 @@
[[constraint]] [[constraint]]
name = "github.com/uber/jaeger-client-go" name = "github.com/uber/jaeger-client-go"
version = "2.9.0" version = "2.14.0"
[[constraint]] [[constraint]]
name = "github.com/uber/jaeger-lib" name = "github.com/uber/jaeger-lib"
version = "1.1.0" version = "1.3.0"
[[constraint]] [[constraint]]
branch = "v1" branch = "v1"

View file

@ -197,6 +197,8 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
SamplingType: "const", SamplingType: "const",
SamplingParam: 1.0, SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831", LocalAgentHostPort: "127.0.0.1:6831",
Propagation: "jaeger",
Gen128Bit: false,
}, },
Zipkin: &zipkin.Config{ Zipkin: &zipkin.Config{
HTTPEndpoint: "http://localhost:9411/api/v1/spans", HTTPEndpoint: "http://localhost:9411/api/v1/spans",

View file

@ -189,6 +189,8 @@ func (gc *GlobalConfiguration) initTracing() {
SamplingType: "const", SamplingType: "const",
SamplingParam: 1.0, SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831", LocalAgentHostPort: "127.0.0.1:6831",
Propagation: "jaeger",
Gen128Bit: false,
} }
} }
if gc.Tracing.Zipkin != nil { if gc.Tracing.Zipkin != nil {

View file

@ -95,6 +95,8 @@ func TestSetEffectiveConfigurationTracing(t *testing.T) {
SamplingType: "const", SamplingType: "const",
SamplingParam: 1.0, SamplingParam: 1.0,
LocalAgentHostPort: "127.0.0.1:6831", LocalAgentHostPort: "127.0.0.1:6831",
Propagation: "jaeger",
Gen128Bit: false,
}, },
Zipkin: nil, Zipkin: nil,
}, },

View file

@ -51,6 +51,18 @@ Træfik supports two backends: Jaeger and Zipkin.
# Default: "127.0.0.1:6831" # Default: "127.0.0.1:6831"
# #
localAgentHostPort = "127.0.0.1:6831" localAgentHostPort = "127.0.0.1:6831"
# Generate 128-bit trace IDs, compatible with OpenCensus
#
# Default: false
gen128Bit = true
# Set the propagation header type. This can be either:
# - "jaeger", jaeger's default trace header.
# - "b3", compatible with OpenZipkin
#
# Default: "jaeger"
propagation = "jaeger"
``` ```
!!! warning !!! warning

View file

@ -1,11 +1,13 @@
package jaeger package jaeger
import ( import (
"fmt"
"io" "io"
"github.com/containous/traefik/log" "github.com/containous/traefik/log"
"github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go"
jaegercfg "github.com/uber/jaeger-client-go/config" jaegercfg "github.com/uber/jaeger-client-go/config"
"github.com/uber/jaeger-client-go/zipkin"
jaegermet "github.com/uber/jaeger-lib/metrics" jaegermet "github.com/uber/jaeger-lib/metrics"
) )
@ -18,6 +20,8 @@ type Config struct {
SamplingType string `description:"set the sampling type." export:"true"` SamplingType string `description:"set the sampling type." export:"true"`
SamplingParam float64 `description:"set the sampling parameter." export:"true"` SamplingParam float64 `description:"set the sampling parameter." export:"true"`
LocalAgentHostPort string `description:"set jaeger-agent's host:port that the reporter will used." export:"false"` LocalAgentHostPort string `description:"set jaeger-agent's host:port that the reporter will used." export:"false"`
Gen128Bit bool `description:"generate 128 bit span IDs." export:"true"`
Propagation string `description:"which propgation format to use (jaeger/b3)." export:"true"`
} }
// Setup sets up the tracer // Setup sets up the tracer
@ -36,11 +40,28 @@ func (c *Config) Setup(componentName string) (opentracing.Tracer, io.Closer, err
jMetricsFactory := jaegermet.NullFactory jMetricsFactory := jaegermet.NullFactory
opts := []jaegercfg.Option{
jaegercfg.Logger(&jaegerLogger{}),
jaegercfg.Metrics(jMetricsFactory),
jaegercfg.Gen128Bit(c.Gen128Bit),
}
switch c.Propagation {
case "b3":
p := zipkin.NewZipkinB3HTTPHeaderPropagator()
opts = append(opts,
jaegercfg.Injector(opentracing.HTTPHeaders, p),
jaegercfg.Extractor(opentracing.HTTPHeaders, p),
)
case "jaeger", "":
default:
return nil, nil, fmt.Errorf("unknown propagation format: %s", c.Propagation)
}
// Initialize tracer with a logger and a metrics factory // Initialize tracer with a logger and a metrics factory
closer, err := jcfg.InitGlobalTracer( closer, err := jcfg.InitGlobalTracer(
componentName, componentName,
jaegercfg.Logger(&jaegerLogger{}), opts...,
jaegercfg.Metrics(jMetricsFactory),
) )
if err != nil { if err != nil {
log.Warnf("Could not initialize jaeger tracer: %s", err.Error()) log.Warnf("Could not initialize jaeger tracer: %s", err.Error())

View file

@ -1,21 +1,201 @@
The MIT License (MIT) Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2017 Uber Technologies, Inc. TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Permission is hereby granted, free of charge, to any person obtaining a copy 1. Definitions.
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:
The above copyright notice and this permission notice shall be included in "License" shall mean the terms and conditions for use, reproduction,
all copies or substantial portions of the Software. 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 "Licensor" shall mean the copyright owner or entity authorized by
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, the copyright owner that is granting the License.
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER "Legal Entity" shall mean the union of the acting entity and all
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, other entities that control, are controlled by, or are under common
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN control with that entity. For the purposes of this definition,
THE SOFTWARE. "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 [yyyy] [name of copyright owner]
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.

View file

@ -0,0 +1,77 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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.
package jaeger
import (
"github.com/opentracing/opentracing-go/log"
"github.com/uber/jaeger-client-go/internal/baggage"
)
// baggageSetter is an actor that can set a baggage value on a Span given certain
// restrictions (eg. maxValueLength).
type baggageSetter struct {
restrictionManager baggage.RestrictionManager
metrics *Metrics
}
func newBaggageSetter(restrictionManager baggage.RestrictionManager, metrics *Metrics) *baggageSetter {
return &baggageSetter{
restrictionManager: restrictionManager,
metrics: metrics,
}
}
// (NB) span should hold the lock before making this call
func (s *baggageSetter) setBaggage(span *Span, key, value string) {
var truncated bool
var prevItem string
restriction := s.restrictionManager.GetRestriction(span.serviceName(), key)
if !restriction.KeyAllowed() {
s.logFields(span, key, value, prevItem, truncated, restriction.KeyAllowed())
s.metrics.BaggageUpdateFailure.Inc(1)
return
}
if len(value) > restriction.MaxValueLength() {
truncated = true
value = value[:restriction.MaxValueLength()]
s.metrics.BaggageTruncate.Inc(1)
}
prevItem = span.context.baggage[key]
s.logFields(span, key, value, prevItem, truncated, restriction.KeyAllowed())
span.context = span.context.WithBaggageItem(key, value)
s.metrics.BaggageUpdateSuccess.Inc(1)
}
func (s *baggageSetter) logFields(span *Span, key, value, prevItem string, truncated, valid bool) {
if !span.context.IsSampled() {
return
}
fields := []log.Field{
log.String("event", "baggage"),
log.String("key", key),
log.String("value", value),
}
if prevItem != "" {
fields = append(fields, log.String("override", "true"))
}
if truncated {
fields = append(fields, log.String("truncated", "true"))
}
if !valid {
fields = append(fields, log.String("invalid", "true"))
}
span.logFieldsNoLocking(fields...)
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017-2018 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package config package config
@ -30,6 +24,8 @@ import (
"github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go" "github.com/uber/jaeger-client-go"
"github.com/uber/jaeger-client-go/internal/baggage/remote"
throttler "github.com/uber/jaeger-client-go/internal/throttler/remote"
"github.com/uber/jaeger-client-go/rpcmetrics" "github.com/uber/jaeger-client-go/rpcmetrics"
) )
@ -37,15 +33,30 @@ const defaultSamplingProbability = 0.001
// Configuration configures and creates Jaeger Tracer // Configuration configures and creates Jaeger Tracer
type Configuration struct { type Configuration struct {
// ServiceName specifies the service name to use on the tracer.
// Can be provided via environment variable named JAEGER_SERVICE_NAME
ServiceName string `yaml:"serviceName"`
// Disabled can be provided via environment variable named JAEGER_DISABLED
Disabled bool `yaml:"disabled"` Disabled bool `yaml:"disabled"`
// RPCMetrics can be provided via environment variable named JAEGER_RPC_METRICS
RPCMetrics bool `yaml:"rpc_metrics"`
// Tags can be provided via environment variable named JAEGER_TAGS
Tags []opentracing.Tag `yaml:"tags"`
Sampler *SamplerConfig `yaml:"sampler"` Sampler *SamplerConfig `yaml:"sampler"`
Reporter *ReporterConfig `yaml:"reporter"` Reporter *ReporterConfig `yaml:"reporter"`
RPCMetrics bool `yaml:"rpc_metrics"` Headers *jaeger.HeadersConfig `yaml:"headers"`
BaggageRestrictions *BaggageRestrictionsConfig `yaml:"baggage_restrictions"`
Throttler *ThrottlerConfig `yaml:"throttler"`
} }
// SamplerConfig allows initializing a non-default sampler. All fields are optional. // SamplerConfig allows initializing a non-default sampler. All fields are optional.
type SamplerConfig struct { type SamplerConfig struct {
// Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote // Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote
// Can be set by exporting an environment variable named JAEGER_SAMPLER_TYPE
Type string `yaml:"type"` Type string `yaml:"type"`
// Param is a value passed to the sampler. // Param is a value passed to the sampler.
@ -55,19 +66,23 @@ type SamplerConfig struct {
// - for "rateLimiting" sampler, the number of spans per second // - for "rateLimiting" sampler, the number of spans per second
// - for "remote" sampler, param is the same as for "probabilistic" // - for "remote" sampler, param is the same as for "probabilistic"
// and indicates the initial sampling rate before the actual one // and indicates the initial sampling rate before the actual one
// is received from the mothership // is received from the mothership.
// Can be set by exporting an environment variable named JAEGER_SAMPLER_PARAM
Param float64 `yaml:"param"` Param float64 `yaml:"param"`
// SamplingServerURL is the address of jaeger-agent's HTTP sampling server // SamplingServerURL is the address of jaeger-agent's HTTP sampling server
// Can be set by exporting an environment variable named JAEGER_SAMPLER_MANAGER_HOST_PORT
SamplingServerURL string `yaml:"samplingServerURL"` SamplingServerURL string `yaml:"samplingServerURL"`
// MaxOperations is the maximum number of operations that the sampler // MaxOperations is the maximum number of operations that the sampler
// will keep track of. If an operation is not tracked, a default probabilistic // will keep track of. If an operation is not tracked, a default probabilistic
// sampler will be used rather than the per operation specific sampler. // sampler will be used rather than the per operation specific sampler.
// Can be set by exporting an environment variable named JAEGER_SAMPLER_MAX_OPERATIONS
MaxOperations int `yaml:"maxOperations"` MaxOperations int `yaml:"maxOperations"`
// SamplingRefreshInterval controls how often the remotely controlled sampler will poll // SamplingRefreshInterval controls how often the remotely controlled sampler will poll
// jaeger-agent for the appropriate sampling strategy. // jaeger-agent for the appropriate sampling strategy.
// Can be set by exporting an environment variable named JAEGER_SAMPLER_REFRESH_INTERVAL
SamplingRefreshInterval time.Duration `yaml:"samplingRefreshInterval"` SamplingRefreshInterval time.Duration `yaml:"samplingRefreshInterval"`
} }
@ -76,34 +91,86 @@ type ReporterConfig struct {
// QueueSize controls how many spans the reporter can keep in memory before it starts dropping // QueueSize controls how many spans the reporter can keep in memory before it starts dropping
// new spans. The queue is continuously drained by a background go-routine, as fast as spans // new spans. The queue is continuously drained by a background go-routine, as fast as spans
// can be sent out of process. // can be sent out of process.
// Can be set by exporting an environment variable named JAEGER_REPORTER_MAX_QUEUE_SIZE
QueueSize int `yaml:"queueSize"` QueueSize int `yaml:"queueSize"`
// BufferFlushInterval controls how often the buffer is force-flushed, even if it's not full. // BufferFlushInterval controls how often the buffer is force-flushed, even if it's not full.
// It is generally not useful, as it only matters for very low traffic services. // It is generally not useful, as it only matters for very low traffic services.
// Can be set by exporting an environment variable named JAEGER_REPORTER_FLUSH_INTERVAL
BufferFlushInterval time.Duration BufferFlushInterval time.Duration
// LogSpans, when true, enables LoggingReporter that runs in parallel with the main reporter // LogSpans, when true, enables LoggingReporter that runs in parallel with the main reporter
// and logs all submitted spans. Main Configuration.Logger must be initialized in the code // and logs all submitted spans. Main Configuration.Logger must be initialized in the code
// for this option to have any effect. // for this option to have any effect.
// Can be set by exporting an environment variable named JAEGER_REPORTER_LOG_SPANS
LogSpans bool `yaml:"logSpans"` LogSpans bool `yaml:"logSpans"`
// LocalAgentHostPort instructs reporter to send spans to jaeger-agent at this address // LocalAgentHostPort instructs reporter to send spans to jaeger-agent at this address
// Can be set by exporting an environment variable named JAEGER_AGENT_HOST / JAEGER_AGENT_PORT
LocalAgentHostPort string `yaml:"localAgentHostPort"` LocalAgentHostPort string `yaml:"localAgentHostPort"`
} }
// BaggageRestrictionsConfig configures the baggage restrictions manager which can be used to whitelist
// certain baggage keys. All fields are optional.
type BaggageRestrictionsConfig struct {
// DenyBaggageOnInitializationFailure controls the startup failure mode of the baggage restriction
// manager. If true, the manager will not allow any baggage to be written until baggage restrictions have
// been retrieved from jaeger-agent. If false, the manager wil allow any baggage to be written until baggage
// restrictions have been retrieved from jaeger-agent.
DenyBaggageOnInitializationFailure bool `yaml:"denyBaggageOnInitializationFailure"`
// HostPort is the hostPort of jaeger-agent's baggage restrictions server
HostPort string `yaml:"hostPort"`
// RefreshInterval controls how often the baggage restriction manager will poll
// jaeger-agent for the most recent baggage restrictions.
RefreshInterval time.Duration `yaml:"refreshInterval"`
}
// ThrottlerConfig configures the throttler which can be used to throttle the
// rate at which the client may send debug requests.
type ThrottlerConfig struct {
// HostPort of jaeger-agent's credit server.
HostPort string `yaml:"hostPort"`
// RefreshInterval controls how often the throttler will poll jaeger-agent
// for more throttling credits.
RefreshInterval time.Duration `yaml:"refreshInterval"`
// SynchronousInitialization determines whether or not the throttler should
// synchronously fetch credits from the agent when an operation is seen for
// the first time. This should be set to true if the client will be used by
// a short lived service that needs to ensure that credits are fetched
// upfront such that sampling or throttling occurs.
SynchronousInitialization bool `yaml:"synchronousInitialization"`
}
type nullCloser struct{} type nullCloser struct{}
func (*nullCloser) Close() error { return nil } func (*nullCloser) Close() error { return nil }
// New creates a new Jaeger Tracer, and a closer func that can be used to flush buffers // New creates a new Jaeger Tracer, and a closer func that can be used to flush buffers
// before shutdown. // before shutdown.
//
// Deprecated: use NewTracer() function
func (c Configuration) New( func (c Configuration) New(
serviceName string, serviceName string,
options ...Option, options ...Option,
) (opentracing.Tracer, io.Closer, error) { ) (opentracing.Tracer, io.Closer, error) {
if serviceName == "" { if serviceName != "" {
c.ServiceName = serviceName
}
return c.NewTracer(options...)
}
// NewTracer returns a new tracer based on the current configuration, using the given options,
// and a closer func that can be used to flush buffers before shutdown.
func (c Configuration) NewTracer(options ...Option) (opentracing.Tracer, io.Closer, error) {
if c.ServiceName == "" {
return nil, nil, errors.New("no service name provided") return nil, nil, errors.New("no service name provided")
} }
if c.Disabled { if c.Disabled {
return &opentracing.NoopTracer{}, &nullCloser{}, nil return &opentracing.NoopTracer{}, &nullCloser{}, nil
} }
@ -127,14 +194,18 @@ func (c Configuration) New(
c.Reporter = &ReporterConfig{} c.Reporter = &ReporterConfig{}
} }
sampler, err := c.Sampler.NewSampler(serviceName, tracerMetrics) sampler := opts.sampler
if sampler == nil {
s, err := c.Sampler.NewSampler(c.ServiceName, tracerMetrics)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
sampler = s
}
reporter := opts.reporter reporter := opts.reporter
if reporter == nil { if reporter == nil {
r, err := c.Reporter.NewReporter(serviceName, tracerMetrics, opts.logger) r, err := c.Reporter.NewReporter(c.ServiceName, tracerMetrics, opts.logger)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -144,6 +215,8 @@ func (c Configuration) New(
tracerOptions := []jaeger.TracerOption{ tracerOptions := []jaeger.TracerOption{
jaeger.TracerOptions.Metrics(tracerMetrics), jaeger.TracerOptions.Metrics(tracerMetrics),
jaeger.TracerOptions.Logger(opts.logger), jaeger.TracerOptions.Logger(opts.logger),
jaeger.TracerOptions.CustomHeaderKeys(c.Headers),
jaeger.TracerOptions.Gen128Bit(opts.gen128Bit),
jaeger.TracerOptions.ZipkinSharedRPCSpan(opts.zipkinSharedRPCSpan), jaeger.TracerOptions.ZipkinSharedRPCSpan(opts.zipkinSharedRPCSpan),
} }
@ -151,6 +224,10 @@ func (c Configuration) New(
tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.Value)) tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.Value))
} }
for _, tag := range c.Tags {
tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.Value))
}
for _, obs := range opts.observers { for _, obs := range opts.observers {
tracerOptions = append(tracerOptions, jaeger.TracerOptions.Observer(obs)) tracerOptions = append(tracerOptions, jaeger.TracerOptions.Observer(obs))
} }
@ -159,11 +236,49 @@ func (c Configuration) New(
tracerOptions = append(tracerOptions, jaeger.TracerOptions.ContribObserver(cobs)) tracerOptions = append(tracerOptions, jaeger.TracerOptions.ContribObserver(cobs))
} }
for format, injector := range opts.injectors {
tracerOptions = append(tracerOptions, jaeger.TracerOptions.Injector(format, injector))
}
for format, extractor := range opts.extractors {
tracerOptions = append(tracerOptions, jaeger.TracerOptions.Extractor(format, extractor))
}
if c.BaggageRestrictions != nil {
mgr := remote.NewRestrictionManager(
c.ServiceName,
remote.Options.Metrics(tracerMetrics),
remote.Options.Logger(opts.logger),
remote.Options.HostPort(c.BaggageRestrictions.HostPort),
remote.Options.RefreshInterval(c.BaggageRestrictions.RefreshInterval),
remote.Options.DenyBaggageOnInitializationFailure(
c.BaggageRestrictions.DenyBaggageOnInitializationFailure,
),
)
tracerOptions = append(tracerOptions, jaeger.TracerOptions.BaggageRestrictionManager(mgr))
}
if c.Throttler != nil {
debugThrottler := throttler.NewThrottler(
c.ServiceName,
throttler.Options.Metrics(tracerMetrics),
throttler.Options.Logger(opts.logger),
throttler.Options.HostPort(c.Throttler.HostPort),
throttler.Options.RefreshInterval(c.Throttler.RefreshInterval),
throttler.Options.SynchronousInitialization(
c.Throttler.SynchronousInitialization,
),
)
tracerOptions = append(tracerOptions, jaeger.TracerOptions.DebugThrottler(debugThrottler))
}
tracer, closer := jaeger.NewTracer( tracer, closer := jaeger.NewTracer(
serviceName, c.ServiceName,
sampler, sampler,
reporter, reporter,
tracerOptions...) tracerOptions...,
)
return tracer, closer, nil return tracer, closer, nil
} }
@ -181,7 +296,7 @@ func (c Configuration) InitGlobalTracer(
if err != nil { if err != nil {
return nil, err return nil, err
} }
opentracing.InitGlobalTracer(tracer) opentracing.SetGlobalTracer(tracer)
return closer, nil return closer, nil
} }

View file

@ -0,0 +1,205 @@
// Copyright (c) 2018 The Jaeger 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.
package config
import (
"fmt"
"os"
"strconv"
"strings"
"time"
opentracing "github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/uber/jaeger-client-go"
)
const (
// environment variable names
envServiceName = "JAEGER_SERVICE_NAME"
envDisabled = "JAEGER_DISABLED"
envRPCMetrics = "JAEGER_RPC_METRICS"
envTags = "JAEGER_TAGS"
envSamplerType = "JAEGER_SAMPLER_TYPE"
envSamplerParam = "JAEGER_SAMPLER_PARAM"
envSamplerManagerHostPort = "JAEGER_SAMPLER_MANAGER_HOST_PORT"
envSamplerMaxOperations = "JAEGER_SAMPLER_MAX_OPERATIONS"
envSamplerRefreshInterval = "JAEGER_SAMPLER_REFRESH_INTERVAL"
envReporterMaxQueueSize = "JAEGER_REPORTER_MAX_QUEUE_SIZE"
envReporterFlushInterval = "JAEGER_REPORTER_FLUSH_INTERVAL"
envReporterLogSpans = "JAEGER_REPORTER_LOG_SPANS"
envAgentHost = "JAEGER_AGENT_HOST"
envAgentPort = "JAEGER_AGENT_PORT"
)
// FromEnv uses environment variables to set the tracer's Configuration
func FromEnv() (*Configuration, error) {
c := &Configuration{}
if e := os.Getenv(envServiceName); e != "" {
c.ServiceName = e
}
if e := os.Getenv(envRPCMetrics); e != "" {
if value, err := strconv.ParseBool(e); err == nil {
c.RPCMetrics = value
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envRPCMetrics, e)
}
}
if e := os.Getenv(envDisabled); e != "" {
if value, err := strconv.ParseBool(e); err == nil {
c.Disabled = value
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envDisabled, e)
}
}
if e := os.Getenv(envTags); e != "" {
c.Tags = parseTags(e)
}
if s, err := samplerConfigFromEnv(); err == nil {
c.Sampler = s
} else {
return nil, errors.Wrap(err, "cannot obtain sampler config from env")
}
if r, err := reporterConfigFromEnv(); err == nil {
c.Reporter = r
} else {
return nil, errors.Wrap(err, "cannot obtain reporter config from env")
}
return c, nil
}
// samplerConfigFromEnv creates a new SamplerConfig based on the environment variables
func samplerConfigFromEnv() (*SamplerConfig, error) {
sc := &SamplerConfig{}
if e := os.Getenv(envSamplerType); e != "" {
sc.Type = e
}
if e := os.Getenv(envSamplerParam); e != "" {
if value, err := strconv.ParseFloat(e, 64); err == nil {
sc.Param = value
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerParam, e)
}
}
if e := os.Getenv(envSamplerManagerHostPort); e != "" {
sc.SamplingServerURL = e
}
if e := os.Getenv(envSamplerMaxOperations); e != "" {
if value, err := strconv.ParseInt(e, 10, 0); err == nil {
sc.MaxOperations = int(value)
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerMaxOperations, e)
}
}
if e := os.Getenv(envSamplerRefreshInterval); e != "" {
if value, err := time.ParseDuration(e); err == nil {
sc.SamplingRefreshInterval = value
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envSamplerRefreshInterval, e)
}
}
return sc, nil
}
// reporterConfigFromEnv creates a new ReporterConfig based on the environment variables
func reporterConfigFromEnv() (*ReporterConfig, error) {
rc := &ReporterConfig{}
if e := os.Getenv(envReporterMaxQueueSize); e != "" {
if value, err := strconv.ParseInt(e, 10, 0); err == nil {
rc.QueueSize = int(value)
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterMaxQueueSize, e)
}
}
if e := os.Getenv(envReporterFlushInterval); e != "" {
if value, err := time.ParseDuration(e); err == nil {
rc.BufferFlushInterval = value
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterFlushInterval, e)
}
}
if e := os.Getenv(envReporterLogSpans); e != "" {
if value, err := strconv.ParseBool(e); err == nil {
rc.LogSpans = value
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envReporterLogSpans, e)
}
}
host := jaeger.DefaultUDPSpanServerHost
if e := os.Getenv(envAgentHost); e != "" {
host = e
}
port := jaeger.DefaultUDPSpanServerPort
if e := os.Getenv(envAgentPort); e != "" {
if value, err := strconv.ParseInt(e, 10, 0); err == nil {
port = int(value)
} else {
return nil, errors.Wrapf(err, "cannot parse env var %s=%s", envAgentPort, e)
}
}
// the side effect of this is that we are building the default value, even if none of the env vars
// were not explicitly passed
rc.LocalAgentHostPort = fmt.Sprintf("%s:%d", host, port)
return rc, nil
}
// parseTags parses the given string into a collection of Tags.
// Spec for this value:
// - comma separated list of key=value
// - value can be specified using the notation ${envVar:defaultValue}, where `envVar`
// is an environment variable and `defaultValue` is the value to use in case the env var is not set
func parseTags(sTags string) []opentracing.Tag {
pairs := strings.Split(sTags, ",")
tags := make([]opentracing.Tag, 0)
for _, p := range pairs {
kv := strings.SplitN(p, "=", 2)
k, v := strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1])
if strings.HasPrefix(v, "${") && strings.HasSuffix(v, "}") {
ed := strings.SplitN(v[2:len(v)-1], ":", 2)
e, d := ed[0], ed[1]
v = os.Getenv(e)
if v == "" && d != "" {
v = d
}
}
tag := opentracing.Tag{Key: k, Value: v}
tags = append(tags, tag)
}
return tags
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package config package config
@ -35,10 +29,14 @@ type Options struct {
metrics metrics.Factory metrics metrics.Factory
logger jaeger.Logger logger jaeger.Logger
reporter jaeger.Reporter reporter jaeger.Reporter
sampler jaeger.Sampler
contribObservers []jaeger.ContribObserver contribObservers []jaeger.ContribObserver
observers []jaeger.Observer observers []jaeger.Observer
gen128Bit bool
zipkinSharedRPCSpan bool zipkinSharedRPCSpan bool
tags []opentracing.Tag tags []opentracing.Tag
injectors map[interface{}]jaeger.Injector
extractors map[interface{}]jaeger.Extractor
} }
// Metrics creates an Option that initializes Metrics in the tracer, // Metrics creates an Option that initializes Metrics in the tracer,
@ -65,6 +63,13 @@ func Reporter(reporter jaeger.Reporter) Option {
} }
} }
// Sampler can be provided explicitly to override the configuration.
func Sampler(sampler jaeger.Sampler) Option {
return func(c *Options) {
c.sampler = sampler
}
}
// Observer can be registered with the Tracer to receive notifications about new Spans. // Observer can be registered with the Tracer to receive notifications about new Spans.
func Observer(observer jaeger.Observer) Option { func Observer(observer jaeger.Observer) Option {
return func(c *Options) { return func(c *Options) {
@ -80,6 +85,13 @@ func ContribObserver(observer jaeger.ContribObserver) Option {
} }
} }
// Gen128Bit specifies whether to generate 128bit trace IDs.
func Gen128Bit(gen128Bit bool) Option {
return func(c *Options) {
c.gen128Bit = gen128Bit
}
}
// ZipkinSharedRPCSpan creates an option that enables sharing span ID between client // ZipkinSharedRPCSpan creates an option that enables sharing span ID between client
// and server spans a la zipkin. If false, client and server spans will be assigned // and server spans a la zipkin. If false, client and server spans will be assigned
// different IDs. // different IDs.
@ -96,8 +108,25 @@ func Tag(key string, value interface{}) Option {
} }
} }
// Injector registers an Injector with the given format.
func Injector(format interface{}, injector jaeger.Injector) Option {
return func(c *Options) {
c.injectors[format] = injector
}
}
// Extractor registers an Extractor with the given format.
func Extractor(format interface{}, extractor jaeger.Extractor) Option {
return func(c *Options) {
c.extractors[format] = extractor
}
}
func applyOptions(options ...Option) Options { func applyOptions(options ...Option) Options {
opts := Options{} opts := Options{
injectors: make(map[interface{}]jaeger.Injector),
extractors: make(map[interface{}]jaeger.Extractor),
}
for _, option := range options { for _, option := range options {
option(&opts) option(&opts)
} }

View file

@ -1,28 +1,22 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package jaeger package jaeger
const ( const (
// JaegerClientVersion is the version of the client library reported as Span tag. // JaegerClientVersion is the version of the client library reported as Span tag.
JaegerClientVersion = "Go-2.9.0" JaegerClientVersion = "Go-2.14.0"
// JaegerClientVersionTagKey is the name of the tag used to report client version. // JaegerClientVersionTagKey is the name of the tag used to report client version.
JaegerClientVersionTagKey = "jaeger.version" JaegerClientVersionTagKey = "jaeger.version"
@ -44,15 +38,22 @@ const (
// TracerIPTagKey used to report ip of the process. // TracerIPTagKey used to report ip of the process.
TracerIPTagKey = "ip" TracerIPTagKey = "ip"
// TracerUUIDTagKey used to report UUID of the client process.
TracerUUIDTagKey = "client-uuid"
// SamplerTypeTagKey reports which sampler was used on the root span. // SamplerTypeTagKey reports which sampler was used on the root span.
SamplerTypeTagKey = "sampler.type" SamplerTypeTagKey = "sampler.type"
// SamplerParamTagKey reports the parameter of the sampler, like sampling probability. // SamplerParamTagKey reports the parameter of the sampler, like sampling probability.
SamplerParamTagKey = "sampler.param" SamplerParamTagKey = "sampler.param"
// TracerStateHeaderName is the http header name used to propagate tracing context. // TraceContextHeaderName is the http header name used to propagate tracing context.
// This must be in lower-case to avoid mismatches when decoding incoming headers. // This must be in lower-case to avoid mismatches when decoding incoming headers.
TracerStateHeaderName = "uber-trace-id" TraceContextHeaderName = "uber-trace-id"
// TracerStateHeaderName is deprecated.
// Deprecated: use TraceContextHeaderName
TracerStateHeaderName = TraceContextHeaderName
// TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage. // TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage.
// This must be in lower-case to avoid mismatches when decoding incoming headers. // This must be in lower-case to avoid mismatches when decoding incoming headers.
@ -73,6 +74,12 @@ const (
SamplerTypeRateLimiting = "ratelimiting" SamplerTypeRateLimiting = "ratelimiting"
// SamplerTypeLowerBound is the type of sampler that samples // SamplerTypeLowerBound is the type of sampler that samples
// only up to a fixed number of traces per second. // at least a fixed number of traces per second.
SamplerTypeLowerBound = "lowerbound" SamplerTypeLowerBound = "lowerbound"
// DefaultUDPSpanServerHost is the default host to send the spans to, via UDP
DefaultUDPSpanServerHost = "localhost"
// DefaultUDPSpanServerPort is the default port to send the spans to, via UDP
DefaultUDPSpanServerPort = 6831
) )

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package jaeger package jaeger

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
/* /*
Package jaeger implements an OpenTracing (http://opentracing.io) Tracer. Package jaeger implements an OpenTracing (http://opentracing.io) Tracer.

64
vendor/github.com/uber/jaeger-client-go/header.go generated vendored Normal file
View file

@ -0,0 +1,64 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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.
package jaeger
// HeadersConfig contains the values for the header keys that Jaeger will use.
// These values may be either custom or default depending on whether custom
// values were provided via a configuration.
type HeadersConfig struct {
// JaegerDebugHeader is the name of HTTP header or a TextMap carrier key which,
// if found in the carrier, forces the trace to be sampled as "debug" trace.
// The value of the header is recorded as the tag on the root span, so that the
// trace can be found in the UI using this value as a correlation ID.
JaegerDebugHeader string `yaml:"jaegerDebugHeader"`
// JaegerBaggageHeader is the name of the HTTP header that is used to submit baggage.
// It differs from TraceBaggageHeaderPrefix in that it can be used only in cases where
// a root span does not exist.
JaegerBaggageHeader string `yaml:"jaegerBaggageHeader"`
// TraceContextHeaderName is the http header name used to propagate tracing context.
// This must be in lower-case to avoid mismatches when decoding incoming headers.
TraceContextHeaderName string `yaml:"TraceContextHeaderName"`
// TraceBaggageHeaderPrefix is the prefix for http headers used to propagate baggage.
// This must be in lower-case to avoid mismatches when decoding incoming headers.
TraceBaggageHeaderPrefix string `yaml:"traceBaggageHeaderPrefix"`
}
func (c *HeadersConfig) applyDefaults() *HeadersConfig {
if c.JaegerBaggageHeader == "" {
c.JaegerBaggageHeader = JaegerBaggageHeader
}
if c.JaegerDebugHeader == "" {
c.JaegerDebugHeader = JaegerDebugHeader
}
if c.TraceBaggageHeaderPrefix == "" {
c.TraceBaggageHeaderPrefix = TraceBaggageHeaderPrefix
}
if c.TraceContextHeaderName == "" {
c.TraceContextHeaderName = TraceContextHeaderName
}
return c
}
func getDefaultHeadersConfig() *HeadersConfig {
return &HeadersConfig{
JaegerDebugHeader: JaegerDebugHeader,
JaegerBaggageHeader: JaegerBaggageHeader,
TraceContextHeaderName: TraceContextHeaderName,
TraceBaggageHeaderPrefix: TraceBaggageHeaderPrefix,
}
}

View file

@ -0,0 +1,101 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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.
package remote
import (
"time"
"github.com/uber/jaeger-client-go"
)
const (
defaultMaxValueLength = 2048
defaultRefreshInterval = time.Minute
defaultHostPort = "localhost:5778"
)
// Option is a function that sets some option on the RestrictionManager
type Option func(options *options)
// Options is a factory for all available options
var Options options
type options struct {
denyBaggageOnInitializationFailure bool
metrics *jaeger.Metrics
logger jaeger.Logger
hostPort string
refreshInterval time.Duration
}
// DenyBaggageOnInitializationFailure creates an Option that determines the startup failure mode of RestrictionManager.
// If DenyBaggageOnInitializationFailure is true, RestrictionManager will not allow any baggage to be written until baggage
// restrictions have been retrieved from agent.
// If DenyBaggageOnInitializationFailure is false, RestrictionManager will allow any baggage to be written until baggage
// restrictions have been retrieved from agent.
func (options) DenyBaggageOnInitializationFailure(b bool) Option {
return func(o *options) {
o.denyBaggageOnInitializationFailure = b
}
}
// Metrics creates an Option that initializes Metrics on the RestrictionManager, which is used to emit statistics.
func (options) Metrics(m *jaeger.Metrics) Option {
return func(o *options) {
o.metrics = m
}
}
// Logger creates an Option that sets the logger used by the RestrictionManager.
func (options) Logger(logger jaeger.Logger) Option {
return func(o *options) {
o.logger = logger
}
}
// HostPort creates an Option that sets the hostPort of the local agent that contains the baggage restrictions.
func (options) HostPort(hostPort string) Option {
return func(o *options) {
o.hostPort = hostPort
}
}
// RefreshInterval creates an Option that sets how often the RestrictionManager will poll local agent for
// the baggage restrictions.
func (options) RefreshInterval(refreshInterval time.Duration) Option {
return func(o *options) {
o.refreshInterval = refreshInterval
}
}
func applyOptions(o ...Option) options {
opts := options{}
for _, option := range o {
option(&opts)
}
if opts.metrics == nil {
opts.metrics = jaeger.NewNullMetrics()
}
if opts.logger == nil {
opts.logger = jaeger.NullLogger
}
if opts.hostPort == "" {
opts.hostPort = defaultHostPort
}
if opts.refreshInterval == 0 {
opts.refreshInterval = defaultRefreshInterval
}
return opts
}

View file

@ -0,0 +1,157 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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.
package remote
import (
"fmt"
"net/url"
"sync"
"time"
"github.com/uber/jaeger-client-go/internal/baggage"
thrift "github.com/uber/jaeger-client-go/thrift-gen/baggage"
"github.com/uber/jaeger-client-go/utils"
)
type httpBaggageRestrictionManagerProxy struct {
url string
}
func newHTTPBaggageRestrictionManagerProxy(hostPort, serviceName string) *httpBaggageRestrictionManagerProxy {
v := url.Values{}
v.Set("service", serviceName)
return &httpBaggageRestrictionManagerProxy{
url: fmt.Sprintf("http://%s/baggageRestrictions?%s", hostPort, v.Encode()),
}
}
func (s *httpBaggageRestrictionManagerProxy) GetBaggageRestrictions(serviceName string) ([]*thrift.BaggageRestriction, error) {
var out []*thrift.BaggageRestriction
if err := utils.GetJSON(s.url, &out); err != nil {
return nil, err
}
return out, nil
}
// RestrictionManager manages baggage restrictions by retrieving baggage restrictions from agent
type RestrictionManager struct {
options
mux sync.RWMutex
serviceName string
restrictions map[string]*baggage.Restriction
thriftProxy thrift.BaggageRestrictionManager
pollStopped sync.WaitGroup
stopPoll chan struct{}
invalidRestriction *baggage.Restriction
validRestriction *baggage.Restriction
// Determines if the manager has successfully retrieved baggage restrictions from agent
initialized bool
}
// NewRestrictionManager returns a BaggageRestrictionManager that polls the agent for the latest
// baggage restrictions.
func NewRestrictionManager(serviceName string, options ...Option) *RestrictionManager {
// TODO there is a developing use case where a single tracer can generate traces on behalf of many services.
// restrictionsMap will need to exist per service
opts := applyOptions(options...)
m := &RestrictionManager{
serviceName: serviceName,
options: opts,
restrictions: make(map[string]*baggage.Restriction),
thriftProxy: newHTTPBaggageRestrictionManagerProxy(opts.hostPort, serviceName),
stopPoll: make(chan struct{}),
invalidRestriction: baggage.NewRestriction(false, 0),
validRestriction: baggage.NewRestriction(true, defaultMaxValueLength),
}
m.pollStopped.Add(1)
go m.pollManager()
return m
}
// isReady returns true if the manager has retrieved baggage restrictions from the remote source.
func (m *RestrictionManager) isReady() bool {
m.mux.RLock()
defer m.mux.RUnlock()
return m.initialized
}
// GetRestriction implements RestrictionManager#GetRestriction.
func (m *RestrictionManager) GetRestriction(service, key string) *baggage.Restriction {
m.mux.RLock()
defer m.mux.RUnlock()
if !m.initialized {
if m.denyBaggageOnInitializationFailure {
return m.invalidRestriction
}
return m.validRestriction
}
if restriction, ok := m.restrictions[key]; ok {
return restriction
}
return m.invalidRestriction
}
// Close stops remote polling and closes the RemoteRestrictionManager.
func (m *RestrictionManager) Close() error {
close(m.stopPoll)
m.pollStopped.Wait()
return nil
}
func (m *RestrictionManager) pollManager() {
defer m.pollStopped.Done()
// attempt to initialize baggage restrictions
if err := m.updateRestrictions(); err != nil {
m.logger.Error(fmt.Sprintf("Failed to initialize baggage restrictions: %s", err.Error()))
}
ticker := time.NewTicker(m.refreshInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := m.updateRestrictions(); err != nil {
m.logger.Error(fmt.Sprintf("Failed to update baggage restrictions: %s", err.Error()))
}
case <-m.stopPoll:
return
}
}
}
func (m *RestrictionManager) updateRestrictions() error {
restrictions, err := m.thriftProxy.GetBaggageRestrictions(m.serviceName)
if err != nil {
m.metrics.BaggageRestrictionsUpdateFailure.Inc(1)
return err
}
newRestrictions := m.parseRestrictions(restrictions)
m.metrics.BaggageRestrictionsUpdateSuccess.Inc(1)
m.mux.Lock()
defer m.mux.Unlock()
m.initialized = true
m.restrictions = newRestrictions
return nil
}
func (m *RestrictionManager) parseRestrictions(restrictions []*thrift.BaggageRestriction) map[string]*baggage.Restriction {
setters := make(map[string]*baggage.Restriction, len(restrictions))
for _, restriction := range restrictions {
setters[restriction.BaggageKey] = baggage.NewRestriction(true, int(restriction.MaxValueLength))
}
return setters
}

View file

@ -0,0 +1,71 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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.
package baggage
const (
defaultMaxValueLength = 2048
)
// Restriction determines whether a baggage key is allowed and contains any restrictions on the baggage value.
type Restriction struct {
keyAllowed bool
maxValueLength int
}
// NewRestriction returns a new Restriction.
func NewRestriction(keyAllowed bool, maxValueLength int) *Restriction {
return &Restriction{
keyAllowed: keyAllowed,
maxValueLength: maxValueLength,
}
}
// KeyAllowed returns whether the baggage key for this restriction is allowed.
func (r *Restriction) KeyAllowed() bool {
return r.keyAllowed
}
// MaxValueLength returns the max length for the baggage value.
func (r *Restriction) MaxValueLength() int {
return r.maxValueLength
}
// RestrictionManager keeps track of valid baggage keys and their restrictions. The manager
// will return a Restriction for a specific baggage key which will determine whether the baggage
// key is allowed for the current service and any other applicable restrictions on the baggage
// value.
type RestrictionManager interface {
GetRestriction(service, key string) *Restriction
}
// DefaultRestrictionManager allows any baggage key.
type DefaultRestrictionManager struct {
defaultRestriction *Restriction
}
// NewDefaultRestrictionManager returns a DefaultRestrictionManager.
func NewDefaultRestrictionManager(maxValueLength int) *DefaultRestrictionManager {
if maxValueLength == 0 {
maxValueLength = defaultMaxValueLength
}
return &DefaultRestrictionManager{
defaultRestriction: &Restriction{keyAllowed: true, maxValueLength: maxValueLength},
}
}
// GetRestriction implements RestrictionManager#GetRestriction.
func (m *DefaultRestrictionManager) GetRestriction(service, key string) *Restriction {
return m.defaultRestriction
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package spanlog package spanlog

View file

@ -0,0 +1,99 @@
// Copyright (c) 2018 The Jaeger 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.
package remote
import (
"time"
"github.com/uber/jaeger-client-go"
)
const (
defaultHostPort = "localhost:5778"
defaultRefreshInterval = time.Second * 5
)
// Option is a function that sets some option on the Throttler
type Option func(options *options)
// Options is a factory for all available options
var Options options
type options struct {
metrics *jaeger.Metrics
logger jaeger.Logger
hostPort string
refreshInterval time.Duration
synchronousInitialization bool
}
// Metrics creates an Option that initializes Metrics on the Throttler, which is used to emit statistics.
func (options) Metrics(m *jaeger.Metrics) Option {
return func(o *options) {
o.metrics = m
}
}
// Logger creates an Option that sets the logger used by the Throttler.
func (options) Logger(logger jaeger.Logger) Option {
return func(o *options) {
o.logger = logger
}
}
// HostPort creates an Option that sets the hostPort of the local agent that keeps track of credits.
func (options) HostPort(hostPort string) Option {
return func(o *options) {
o.hostPort = hostPort
}
}
// RefreshInterval creates an Option that sets how often the Throttler will poll local agent for
// credits.
func (options) RefreshInterval(refreshInterval time.Duration) Option {
return func(o *options) {
o.refreshInterval = refreshInterval
}
}
// SynchronousInitialization creates an Option that determines whether the throttler should synchronously
// fetch credits from the agent when an operation is seen for the first time. This should be set to true
// if the client will be used by a short lived service that needs to ensure that credits are fetched upfront
// such that sampling or throttling occurs.
func (options) SynchronousInitialization(b bool) Option {
return func(o *options) {
o.synchronousInitialization = b
}
}
func applyOptions(o ...Option) options {
opts := options{}
for _, option := range o {
option(&opts)
}
if opts.metrics == nil {
opts.metrics = jaeger.NewNullMetrics()
}
if opts.logger == nil {
opts.logger = jaeger.NullLogger
}
if opts.hostPort == "" {
opts.hostPort = defaultHostPort
}
if opts.refreshInterval == 0 {
opts.refreshInterval = defaultRefreshInterval
}
return opts
}

View file

@ -0,0 +1,216 @@
// Copyright (c) 2018 The Jaeger 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.
package remote
import (
"fmt"
"net/url"
"sync"
"sync/atomic"
"time"
"github.com/pkg/errors"
"github.com/uber/jaeger-client-go"
"github.com/uber/jaeger-client-go/utils"
)
const (
// minimumCredits is the minimum amount of credits necessary to not be throttled.
// i.e. if currentCredits > minimumCredits, then the operation will not be throttled.
minimumCredits = 1.0
)
var (
errorUUIDNotSet = errors.New("Throttler UUID must be set")
)
type operationBalance struct {
Operation string `json:"operation"`
Balance float64 `json:"balance"`
}
type creditResponse struct {
Balances []operationBalance `json:"balances"`
}
type httpCreditManagerProxy struct {
hostPort string
}
func newHTTPCreditManagerProxy(hostPort string) *httpCreditManagerProxy {
return &httpCreditManagerProxy{
hostPort: hostPort,
}
}
// N.B. Operations list must not be empty.
func (m *httpCreditManagerProxy) FetchCredits(uuid, serviceName string, operations []string) (*creditResponse, error) {
params := url.Values{}
params.Set("service", serviceName)
params.Set("uuid", uuid)
for _, op := range operations {
params.Add("operations", op)
}
var resp creditResponse
if err := utils.GetJSON(fmt.Sprintf("http://%s/credits?%s", m.hostPort, params.Encode()), &resp); err != nil {
return nil, errors.Wrap(err, "Failed to receive credits from agent")
}
return &resp, nil
}
// Throttler retrieves credits from agent and uses it to throttle operations.
type Throttler struct {
options
mux sync.RWMutex
service string
uuid atomic.Value
creditManager *httpCreditManagerProxy
credits map[string]float64 // map of operation->credits
close chan struct{}
stopped sync.WaitGroup
}
// NewThrottler returns a Throttler that polls agent for credits and uses them to throttle
// the service.
func NewThrottler(service string, options ...Option) *Throttler {
opts := applyOptions(options...)
creditManager := newHTTPCreditManagerProxy(opts.hostPort)
t := &Throttler{
options: opts,
creditManager: creditManager,
service: service,
credits: make(map[string]float64),
close: make(chan struct{}),
}
t.stopped.Add(1)
go t.pollManager()
return t
}
// IsAllowed implements Throttler#IsAllowed.
func (t *Throttler) IsAllowed(operation string) bool {
t.mux.Lock()
defer t.mux.Unlock()
value, ok := t.credits[operation]
if !ok || value == 0 {
if !ok {
// NOTE: This appears to be a no-op at first glance, but it stores
// the operation key in the map. Necessary for functionality of
// Throttler#operations method.
t.credits[operation] = 0
}
if !t.synchronousInitialization {
t.metrics.ThrottledDebugSpans.Inc(1)
return false
}
// If it is the first time this operation is being checked, synchronously fetch
// the credits.
credits, err := t.fetchCredits([]string{operation})
if err != nil {
// Failed to receive credits from agent, try again next time
t.logger.Error("Failed to fetch credits: " + err.Error())
return false
}
if len(credits.Balances) == 0 {
// This shouldn't happen but just in case
return false
}
for _, opBalance := range credits.Balances {
t.credits[opBalance.Operation] += opBalance.Balance
}
}
return t.isAllowed(operation)
}
// Close stops the throttler from fetching credits from remote.
func (t *Throttler) Close() error {
close(t.close)
t.stopped.Wait()
return nil
}
// SetProcess implements ProcessSetter#SetProcess. It's imperative that the UUID is set before any remote
// requests are made.
func (t *Throttler) SetProcess(process jaeger.Process) {
if process.UUID != "" {
t.uuid.Store(process.UUID)
}
}
// N.B. This function must be called with the Write Lock
func (t *Throttler) isAllowed(operation string) bool {
credits := t.credits[operation]
if credits < minimumCredits {
t.metrics.ThrottledDebugSpans.Inc(1)
return false
}
t.credits[operation] = credits - minimumCredits
return true
}
func (t *Throttler) pollManager() {
defer t.stopped.Done()
ticker := time.NewTicker(t.refreshInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
t.refreshCredits()
case <-t.close:
return
}
}
}
func (t *Throttler) operations() []string {
t.mux.RLock()
defer t.mux.RUnlock()
operations := make([]string, 0, len(t.credits))
for op := range t.credits {
operations = append(operations, op)
}
return operations
}
func (t *Throttler) refreshCredits() {
operations := t.operations()
if len(operations) == 0 {
return
}
newCredits, err := t.fetchCredits(operations)
if err != nil {
t.metrics.ThrottlerUpdateFailure.Inc(1)
t.logger.Error("Failed to fetch credits: " + err.Error())
return
}
t.metrics.ThrottlerUpdateSuccess.Inc(1)
t.mux.Lock()
defer t.mux.Unlock()
for _, opBalance := range newCredits.Balances {
t.credits[opBalance.Operation] += opBalance.Balance
}
}
func (t *Throttler) fetchCredits(operations []string) (*creditResponse, error) {
uuid := t.uuid.Load()
uuidStr, _ := uuid.(string)
if uuid == nil || uuidStr == "" {
return nil, errorUUIDNotSet
}
return t.creditManager.FetchCredits(uuidStr, t.service, operations)
}

View file

@ -0,0 +1,32 @@
// Copyright (c) 2018 The Jaeger 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.
package throttler
// Throttler is used to rate limits operations. For example, given how debug spans
// are always sampled, a throttler can be enabled per client to rate limit the amount
// of debug spans a client can start.
type Throttler interface {
// IsAllowed determines whether the operation should be allowed and not be
// throttled.
IsAllowed(operation string) bool
}
// DefaultThrottler doesn't throttle at all.
type DefaultThrottler struct{}
// IsAllowed implements Throttler#IsAllowed.
func (t DefaultThrottler) IsAllowed(operation string) bool {
return true
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger
@ -31,6 +25,8 @@ import (
// BuildJaegerThrift builds jaeger span based on internal span. // BuildJaegerThrift builds jaeger span based on internal span.
func BuildJaegerThrift(span *Span) *j.Span { func BuildJaegerThrift(span *Span) *j.Span {
span.Lock()
defer span.Unlock()
startTime := utils.TimeToMicrosecondsSinceEpochInt64(span.startTime) startTime := utils.TimeToMicrosecondsSinceEpochInt64(span.startTime)
duration := span.duration.Nanoseconds() / int64(time.Microsecond) duration := span.duration.Nanoseconds() / int64(time.Microsecond)
jaegerSpan := &j.Span{ jaegerSpan := &j.Span{
@ -51,6 +47,8 @@ func BuildJaegerThrift(span *Span) *j.Span {
// BuildJaegerProcessThrift creates a thrift Process type. // BuildJaegerProcessThrift creates a thrift Process type.
func BuildJaegerProcessThrift(span *Span) *j.Process { func BuildJaegerProcessThrift(span *Span) *j.Process {
span.Lock()
defer span.Unlock()
return buildJaegerProcessThrift(span.tracer) return buildJaegerProcessThrift(span.tracer)
} }
@ -59,6 +57,9 @@ func buildJaegerProcessThrift(tracer *Tracer) *j.Process {
ServiceName: tracer.serviceName, ServiceName: tracer.serviceName,
Tags: buildTags(tracer.tags), Tags: buildTags(tracer.tags),
} }
if tracer.process.UUID != "" {
process.Tags = append(process.Tags, &j.Tag{Key: TracerUUIDTagKey, VStr: &tracer.process.UUID, VType: j.TagType_STRING})
}
return process return process
} }

View file

@ -1,26 +1,25 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package log package log
import "log" import (
"bytes"
"fmt"
"log"
"sync"
)
// Logger provides an abstract interface for logging from Reporters. // Logger provides an abstract interface for logging from Reporters.
// Applications can provide their own implementation of this interface to adapt // Applications can provide their own implementation of this interface to adapt
@ -48,10 +47,44 @@ func (l *stdLogger) Infof(msg string, args ...interface{}) {
log.Printf(msg, args...) log.Printf(msg, args...)
} }
// NullLogger is implementation of the Logger interface that delegates to default `log` package // NullLogger is implementation of the Logger interface that is no-op
var NullLogger = &nullLogger{} var NullLogger = &nullLogger{}
type nullLogger struct{} type nullLogger struct{}
func (l *nullLogger) Error(msg string) {} func (l *nullLogger) Error(msg string) {}
func (l *nullLogger) Infof(msg string, args ...interface{}) {} func (l *nullLogger) Infof(msg string, args ...interface{}) {}
// BytesBufferLogger implements Logger backed by a bytes.Buffer.
type BytesBufferLogger struct {
mux sync.Mutex
buf bytes.Buffer
}
// Error implements Logger.
func (l *BytesBufferLogger) Error(msg string) {
l.mux.Lock()
l.buf.WriteString(fmt.Sprintf("ERROR: %s\n", msg))
l.mux.Unlock()
}
// Infof implements Logger.
func (l *BytesBufferLogger) Infof(msg string, args ...interface{}) {
l.mux.Lock()
l.buf.WriteString("INFO: " + fmt.Sprintf(msg, args...) + "\n")
l.mux.Unlock()
}
// String returns string representation of the underlying buffer.
func (l *BytesBufferLogger) String() string {
l.mux.Lock()
defer l.mux.Unlock()
return l.buf.String()
}
// Flush empties the underlying buffer.
func (l *BytesBufferLogger) Flush() {
l.mux.Lock()
defer l.mux.Unlock()
l.buf.Reset()
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017-2018 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger
@ -39,48 +33,70 @@ type Metrics struct {
TracesJoinedNotSampled metrics.Counter `metric:"traces" tags:"state=joined,sampled=n"` TracesJoinedNotSampled metrics.Counter `metric:"traces" tags:"state=joined,sampled=n"`
// Number of sampled spans started by this tracer // Number of sampled spans started by this tracer
SpansStarted metrics.Counter `metric:"spans" tags:"group=lifecycle,state=started"` SpansStartedSampled metrics.Counter `metric:"started_spans" tags:"sampled=y"`
// Number of sampled spans finished by this tracer // Number of unsampled spans started by this tracer
SpansFinished metrics.Counter `metric:"spans" tags:"group=lifecycle,state=finished"` SpansStartedNotSampled metrics.Counter `metric:"started_spans" tags:"sampled=n"`
// Number of sampled spans started by this tracer // Number of spans finished by this tracer
SpansSampled metrics.Counter `metric:"spans" tags:"group=sampling,sampled=y"` SpansFinished metrics.Counter `metric:"finished_spans"`
// Number of not-sampled spans started by this tracer
SpansNotSampled metrics.Counter `metric:"spans" tags:"group=sampling,sampled=n"`
// Number of errors decoding tracing context // Number of errors decoding tracing context
DecodingErrors metrics.Counter `metric:"decoding-errors"` DecodingErrors metrics.Counter `metric:"span_context_decoding_errors"`
// Number of spans successfully reported // Number of spans successfully reported
ReporterSuccess metrics.Counter `metric:"reporter-spans" tags:"state=success"` ReporterSuccess metrics.Counter `metric:"reporter_spans" tags:"result=ok"`
// Number of spans in failed attempts to report // Number of spans not reported due to a Sender failure
ReporterFailure metrics.Counter `metric:"reporter-spans" tags:"state=failure"` ReporterFailure metrics.Counter `metric:"reporter_spans" tags:"result=err"`
// Number of spans dropped due to internal queue overflow // Number of spans dropped due to internal queue overflow
ReporterDropped metrics.Counter `metric:"reporter-spans" tags:"state=dropped"` ReporterDropped metrics.Counter `metric:"reporter_spans" tags:"result=dropped"`
// Current number of spans in the reporter queue // Current number of spans in the reporter queue
ReporterQueueLength metrics.Gauge `metric:"reporter-queue"` ReporterQueueLength metrics.Gauge `metric:"reporter_queue_length"`
// Number of times the Sampler succeeded to retrieve sampling strategy // Number of times the Sampler succeeded to retrieve sampling strategy
SamplerRetrieved metrics.Counter `metric:"sampler" tags:"state=retrieved"` SamplerRetrieved metrics.Counter `metric:"sampler_queries" tags:"result=ok"`
// Number of times the Sampler succeeded to retrieve and update sampling strategy
SamplerUpdated metrics.Counter `metric:"sampler" tags:"state=updated"`
// Number of times the Sampler failed to update sampling strategy
SamplerUpdateFailure metrics.Counter `metric:"sampler" tags:"state=failure,phase=updating"`
// Number of times the Sampler failed to retrieve sampling strategy // Number of times the Sampler failed to retrieve sampling strategy
SamplerQueryFailure metrics.Counter `metric:"sampler" tags:"state=failure,phase=query"` SamplerQueryFailure metrics.Counter `metric:"sampler_queries" tags:"result=err"`
// Number of times the Sampler succeeded to retrieve and update sampling strategy
SamplerUpdated metrics.Counter `metric:"sampler_updates" tags:"result=ok"`
// Number of times the Sampler failed to update sampling strategy
SamplerUpdateFailure metrics.Counter `metric:"sampler_updates" tags:"result=err"`
// Number of times baggage was successfully written or updated on spans.
BaggageUpdateSuccess metrics.Counter `metric:"baggage_updates" tags:"result=ok"`
// Number of times baggage failed to write or update on spans.
BaggageUpdateFailure metrics.Counter `metric:"baggage_updates" tags:"result=err"`
// Number of times baggage was truncated as per baggage restrictions.
BaggageTruncate metrics.Counter `metric:"baggage_truncations"`
// Number of times baggage restrictions were successfully updated.
BaggageRestrictionsUpdateSuccess metrics.Counter `metric:"baggage_restrictions_updates" tags:"result=ok"`
// Number of times baggage restrictions failed to update.
BaggageRestrictionsUpdateFailure metrics.Counter `metric:"baggage_restrictions_updates" tags:"result=err"`
// Number of times debug spans were throttled.
ThrottledDebugSpans metrics.Counter `metric:"throttled_debug_spans"`
// Number of times throttler successfully updated.
ThrottlerUpdateSuccess metrics.Counter `metric:"throttler_updates" tags:"result=ok"`
// Number of times throttler failed to update.
ThrottlerUpdateFailure metrics.Counter `metric:"throttler_updates" tags:"result=err"`
} }
// NewMetrics creates a new Metrics struct and initializes it. // NewMetrics creates a new Metrics struct and initializes it.
func NewMetrics(factory metrics.Factory, globalTags map[string]string) *Metrics { func NewMetrics(factory metrics.Factory, globalTags map[string]string) *Metrics {
m := &Metrics{} m := &Metrics{}
// TODO the namespace "jaeger" should be configurable (e.g. in all-in-one "jaeger-client" would make more sense)
metrics.Init(m, factory.Namespace("jaeger", nil), globalTags) metrics.Init(m, factory.Namespace("jaeger", nil), globalTags)
return m return m
} }

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

29
vendor/github.com/uber/jaeger-client-go/process.go generated vendored Normal file
View file

@ -0,0 +1,29 @@
// Copyright (c) 2018 The Jaeger 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.
package jaeger
// Process holds process specific metadata that's relevant to this client.
type Process struct {
Service string
UUID string
Tags []Tag
}
// ProcessSetter sets a process. This can be used by any class that requires
// the process to be set as part of initialization.
// See internal/throttler/remote/throttler.go for an example.
type ProcessSetter interface {
SetProcess(process Process)
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger
@ -58,14 +52,16 @@ type Extractor interface {
} }
type textMapPropagator struct { type textMapPropagator struct {
tracer *Tracer headerKeys *HeadersConfig
metrics Metrics
encodeValue func(string) string encodeValue func(string) string
decodeValue func(string) string decodeValue func(string) string
} }
func newTextMapPropagator(tracer *Tracer) *textMapPropagator { func newTextMapPropagator(headerKeys *HeadersConfig, metrics Metrics) *textMapPropagator {
return &textMapPropagator{ return &textMapPropagator{
tracer: tracer, headerKeys: headerKeys,
metrics: metrics,
encodeValue: func(val string) string { encodeValue: func(val string) string {
return val return val
}, },
@ -75,9 +71,10 @@ func newTextMapPropagator(tracer *Tracer) *textMapPropagator {
} }
} }
func newHTTPHeaderPropagator(tracer *Tracer) *textMapPropagator { func newHTTPHeaderPropagator(headerKeys *HeadersConfig, metrics Metrics) *textMapPropagator {
return &textMapPropagator{ return &textMapPropagator{
tracer: tracer, headerKeys: headerKeys,
metrics: metrics,
encodeValue: func(val string) string { encodeValue: func(val string) string {
return url.QueryEscape(val) return url.QueryEscape(val)
}, },
@ -115,9 +112,9 @@ func (p *textMapPropagator) Inject(
// Do not encode the string with trace context to avoid accidental double-encoding // Do not encode the string with trace context to avoid accidental double-encoding
// if people are using opentracing < 0.10.0. Our colon-separated representation // if people are using opentracing < 0.10.0. Our colon-separated representation
// of the trace context is already safe for HTTP headers. // of the trace context is already safe for HTTP headers.
textMapWriter.Set(TracerStateHeaderName, sc.String()) textMapWriter.Set(p.headerKeys.TraceContextHeaderName, sc.String())
for k, v := range sc.baggage { for k, v := range sc.baggage {
safeKey := addBaggageKeyPrefix(k) safeKey := p.addBaggageKeyPrefix(k)
safeVal := p.encodeValue(v) safeVal := p.encodeValue(v)
textMapWriter.Set(safeKey, safeVal) textMapWriter.Set(safeKey, safeVal)
} }
@ -133,33 +130,33 @@ func (p *textMapPropagator) Extract(abstractCarrier interface{}) (SpanContext, e
var baggage map[string]string var baggage map[string]string
err := textMapReader.ForeachKey(func(rawKey, value string) error { err := textMapReader.ForeachKey(func(rawKey, value string) error {
key := strings.ToLower(rawKey) // TODO not necessary for plain TextMap key := strings.ToLower(rawKey) // TODO not necessary for plain TextMap
if key == TracerStateHeaderName { if key == p.headerKeys.TraceContextHeaderName {
var err error var err error
safeVal := p.decodeValue(value) safeVal := p.decodeValue(value)
if ctx, err = ContextFromString(safeVal); err != nil { if ctx, err = ContextFromString(safeVal); err != nil {
return err return err
} }
} else if key == JaegerDebugHeader { } else if key == p.headerKeys.JaegerDebugHeader {
ctx.debugID = p.decodeValue(value) ctx.debugID = p.decodeValue(value)
} else if key == JaegerBaggageHeader { } else if key == p.headerKeys.JaegerBaggageHeader {
if baggage == nil { if baggage == nil {
baggage = make(map[string]string) baggage = make(map[string]string)
} }
for k, v := range parseCommaSeparatedMap(value) { for k, v := range p.parseCommaSeparatedMap(value) {
baggage[k] = v baggage[k] = v
} }
} else if strings.HasPrefix(key, TraceBaggageHeaderPrefix) { } else if strings.HasPrefix(key, p.headerKeys.TraceBaggageHeaderPrefix) {
if baggage == nil { if baggage == nil {
baggage = make(map[string]string) baggage = make(map[string]string)
} }
safeKey := removeBaggageKeyPrefix(key) safeKey := p.removeBaggageKeyPrefix(key)
safeVal := p.decodeValue(value) safeVal := p.decodeValue(value)
baggage[safeKey] = safeVal baggage[safeKey] = safeVal
} }
return nil return nil
}) })
if err != nil { if err != nil {
p.tracer.metrics.DecodingErrors.Inc(1) p.metrics.DecodingErrors.Inc(1)
return emptyContext, err return emptyContext, err
} }
if !ctx.traceID.IsValid() && ctx.debugID == "" && len(baggage) == 0 { if !ctx.traceID.IsValid() && ctx.debugID == "" && len(baggage) == 0 {
@ -272,7 +269,7 @@ func (p *binaryPropagator) Extract(abstractCarrier interface{}) (SpanContext, er
// is converted to map[string]string { "key1" : "value1", // is converted to map[string]string { "key1" : "value1",
// "key2" : "value2", // "key2" : "value2",
// "key3" : "value3" } // "key3" : "value3" }
func parseCommaSeparatedMap(value string) map[string]string { func (p *textMapPropagator) parseCommaSeparatedMap(value string) map[string]string {
baggage := make(map[string]string) baggage := make(map[string]string)
value, err := url.QueryUnescape(value) value, err := url.QueryUnescape(value)
if err != nil { if err != nil {
@ -284,7 +281,7 @@ func parseCommaSeparatedMap(value string) map[string]string {
if len(kv) == 2 { if len(kv) == 2 {
baggage[kv[0]] = kv[1] baggage[kv[0]] = kv[1]
} else { } else {
log.Printf("Malformed value passed in for %s", JaegerBaggageHeader) log.Printf("Malformed value passed in for %s", p.headerKeys.JaegerBaggageHeader)
} }
} }
return baggage return baggage
@ -292,12 +289,12 @@ func parseCommaSeparatedMap(value string) map[string]string {
// Converts a baggage item key into an http header format, // Converts a baggage item key into an http header format,
// by prepending TraceBaggageHeaderPrefix and encoding the key string // by prepending TraceBaggageHeaderPrefix and encoding the key string
func addBaggageKeyPrefix(key string) string { func (p *textMapPropagator) addBaggageKeyPrefix(key string) string {
// TODO encodeBaggageKeyAsHeader add caching and escaping // TODO encodeBaggageKeyAsHeader add caching and escaping
return fmt.Sprintf("%v%v", TraceBaggageHeaderPrefix, key) return fmt.Sprintf("%v%v", p.headerKeys.TraceBaggageHeaderPrefix, key)
} }
func removeBaggageKeyPrefix(key string) string { func (p *textMapPropagator) removeBaggageKeyPrefix(key string) string {
// TODO decodeBaggageHeaderKey add caching and escaping // TODO decodeBaggageHeaderKey add caching and escaping
return key[len(TraceBaggageHeaderPrefix):] return key[len(p.headerKeys.TraceBaggageHeaderPrefix):]
} }

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,26 +1,21 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger
import ( import (
"fmt"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -155,26 +150,40 @@ func (r *compositeReporter) Close() {
} }
} }
// ------------------------------ // ------------- REMOTE REPORTER -----------------
type reporterQueueItemType int
const ( const (
defaultQueueSize = 100 defaultQueueSize = 100
defaultBufferFlushInterval = 10 * time.Second defaultBufferFlushInterval = 1 * time.Second
reporterQueueItemSpan reporterQueueItemType = iota
reporterQueueItemClose
) )
type remoteReporter struct { type reporterQueueItem struct {
// must be first in the struct because `sync/atomic` expects 64-bit alignment. itemType reporterQueueItemType
// Cf. https://github.com/uber/jaeger-client-go/issues/155, https://goo.gl/zW7dgq span *Span
queueLength int64 close *sync.WaitGroup
reporterOptions
sender Transport
queue chan *Span
queueDrained sync.WaitGroup
flushSignal chan *sync.WaitGroup
} }
// NewRemoteReporter creates a new reporter that sends spans out of process by means of Sender type remoteReporter struct {
// These fields must be first in the struct because `sync/atomic` expects 64-bit alignment.
// Cf. https://github.com/uber/jaeger-client-go/issues/155, https://goo.gl/zW7dgq
queueLength int64
closed int64 // 0 - not closed, 1 - closed
reporterOptions
sender Transport
queue chan reporterQueueItem
}
// NewRemoteReporter creates a new reporter that sends spans out of process by means of Sender.
// Calls to Report(Span) return immediately (side effect: if internal buffer is full the span is dropped).
// Periodically the transport buffer is flushed even if it hasn't reached max packet size.
// Calls to Close() block until all spans reported prior to the call to Close are flushed.
func NewRemoteReporter(sender Transport, opts ...ReporterOption) Reporter { func NewRemoteReporter(sender Transport, opts ...ReporterOption) Reporter {
options := reporterOptions{} options := reporterOptions{}
for _, option := range opts { for _, option := range opts {
@ -195,18 +204,21 @@ func NewRemoteReporter(sender Transport, opts ...ReporterOption) Reporter {
reporter := &remoteReporter{ reporter := &remoteReporter{
reporterOptions: options, reporterOptions: options,
sender: sender, sender: sender,
flushSignal: make(chan *sync.WaitGroup), queue: make(chan reporterQueueItem, options.queueSize),
queue: make(chan *Span, options.queueSize),
} }
go reporter.processQueue() go reporter.processQueue()
return reporter return reporter
} }
// Report implements Report() method of Reporter. // Report implements Report() method of Reporter.
// It passes the span to a background go-routine for submission to Jaeger. // It passes the span to a background go-routine for submission to Jaeger backend.
// If the internal queue is full, the span is dropped and metrics.ReporterDropped counter is incremented.
// If Report() is called after the reporter has been Close()-ed, the additional spans will not be
// sent to the backend, but the metrics.ReporterDropped counter may not reflect them correctly,
// because some of them may still be successfully added to the queue.
func (r *remoteReporter) Report(span *Span) { func (r *remoteReporter) Report(span *Span) {
select { select {
case r.queue <- span: case r.queue <- reporterQueueItem{itemType: reporterQueueItemSpan, span: span}:
atomic.AddInt64(&r.queueLength, 1) atomic.AddInt64(&r.queueLength, 1)
default: default:
r.metrics.ReporterDropped.Inc(1) r.metrics.ReporterDropped.Inc(1)
@ -215,53 +227,63 @@ func (r *remoteReporter) Report(span *Span) {
// Close implements Close() method of Reporter by waiting for the queue to be drained. // Close implements Close() method of Reporter by waiting for the queue to be drained.
func (r *remoteReporter) Close() { func (r *remoteReporter) Close() {
r.queueDrained.Add(1) if swapped := atomic.CompareAndSwapInt64(&r.closed, 0, 1); !swapped {
close(r.queue) r.logger.Error("Repeated attempt to close the reporter is ignored")
r.queueDrained.Wait() return
}
r.sendCloseEvent()
r.sender.Close() r.sender.Close()
} }
func (r *remoteReporter) sendCloseEvent() {
wg := &sync.WaitGroup{}
wg.Add(1)
item := reporterQueueItem{itemType: reporterQueueItemClose, close: wg}
r.queue <- item // if the queue is full we will block until there is space
atomic.AddInt64(&r.queueLength, 1)
wg.Wait()
}
// processQueue reads spans from the queue, converts them to Thrift, and stores them in an internal buffer. // processQueue reads spans from the queue, converts them to Thrift, and stores them in an internal buffer.
// When the buffer length reaches batchSize, it is flushed by submitting the accumulated spans to Jaeger. // When the buffer length reaches batchSize, it is flushed by submitting the accumulated spans to Jaeger.
// Buffer also gets flushed automatically every batchFlushInterval seconds, just in case the tracer stopped // Buffer also gets flushed automatically every batchFlushInterval seconds, just in case the tracer stopped
// reporting new spans. // reporting new spans.
func (r *remoteReporter) processQueue() { func (r *remoteReporter) processQueue() {
// flush causes the Sender to flush its accumulated spans and clear the buffer
flush := func() {
if flushed, err := r.sender.Flush(); err != nil {
r.metrics.ReporterFailure.Inc(int64(flushed))
r.logger.Error(fmt.Sprintf("error when flushing the buffer: %s", err.Error()))
} else if flushed > 0 {
r.metrics.ReporterSuccess.Inc(int64(flushed))
}
}
timer := time.NewTicker(r.bufferFlushInterval) timer := time.NewTicker(r.bufferFlushInterval)
for { for {
select { select {
case span, ok := <-r.queue: case <-timer.C:
if ok { flush()
case item := <-r.queue:
atomic.AddInt64(&r.queueLength, -1) atomic.AddInt64(&r.queueLength, -1)
switch item.itemType {
case reporterQueueItemSpan:
span := item.span
if flushed, err := r.sender.Append(span); err != nil { if flushed, err := r.sender.Append(span); err != nil {
r.metrics.ReporterFailure.Inc(int64(flushed)) r.metrics.ReporterFailure.Inc(int64(flushed))
r.logger.Error(err.Error()) r.logger.Error(fmt.Sprintf("error reporting span %q: %s", span.OperationName(), err.Error()))
} else if flushed > 0 { } else if flushed > 0 {
r.metrics.ReporterSuccess.Inc(int64(flushed)) r.metrics.ReporterSuccess.Inc(int64(flushed))
// to reduce the number of gauge stats, we only emit queue length on flush // to reduce the number of gauge stats, we only emit queue length on flush
r.metrics.ReporterQueueLength.Update(atomic.LoadInt64(&r.queueLength)) r.metrics.ReporterQueueLength.Update(atomic.LoadInt64(&r.queueLength))
} }
} else { case reporterQueueItemClose:
// queue closed
timer.Stop() timer.Stop()
r.flush() flush()
r.queueDrained.Done() item.close.Done()
return return
} }
case <-timer.C:
r.flush()
case wg := <-r.flushSignal: // for testing
r.flush()
wg.Done()
} }
} }
} }
// flush causes the Sender to flush its accumulated spans and clear the buffer
func (r *remoteReporter) flush() {
if flushed, err := r.sender.Flush(); err != nil {
r.metrics.ReporterFailure.Inc(int64(flushed))
r.logger.Error(err.Error())
} else if flushed > 0 {
r.metrics.ReporterSuccess.Inc(int64(flushed))
}
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Package rpcmetrics implements an Observer that can be used to emit RPC metrics. // Package rpcmetrics implements an Observer that can be used to emit RPC metrics.
package rpcmetrics package rpcmetrics

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package rpcmetrics package rpcmetrics

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package rpcmetrics package rpcmetrics

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package rpcmetrics package rpcmetrics

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package rpcmetrics package rpcmetrics

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger
@ -25,6 +19,7 @@ import (
"math" "math"
"net/url" "net/url"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/uber/jaeger-client-go/log" "github.com/uber/jaeger-client-go/log"
@ -338,6 +333,7 @@ func (s *adaptiveSampler) Close() {
for _, sampler := range s.samplers { for _, sampler := range s.samplers {
sampler.Close() sampler.Close()
} }
s.defaultSampler.Close()
} }
func (s *adaptiveSampler) Equal(other Sampler) bool { func (s *adaptiveSampler) Equal(other Sampler) bool {
@ -378,13 +374,16 @@ func (s *adaptiveSampler) update(strategies *sampling.PerOperationSamplingStrate
// for the appropriate sampling strategy, constructs a corresponding sampler and // for the appropriate sampling strategy, constructs a corresponding sampler and
// delegates to it for sampling decisions. // delegates to it for sampling decisions.
type RemotelyControlledSampler struct { type RemotelyControlledSampler struct {
// These fields must be first in the struct because `sync/atomic` expects 64-bit alignment.
// Cf. https://github.com/uber/jaeger-client-go/issues/155, https://goo.gl/zW7dgq
closed int64 // 0 - not closed, 1 - closed
sync.RWMutex sync.RWMutex
samplerOptions samplerOptions
serviceName string serviceName string
timer *time.Ticker
manager sampling.SamplingManager manager sampling.SamplingManager
pollStopped sync.WaitGroup doneChan chan *sync.WaitGroup
} }
type httpSamplingManager struct { type httpSamplingManager struct {
@ -411,10 +410,9 @@ func NewRemotelyControlledSampler(
sampler := &RemotelyControlledSampler{ sampler := &RemotelyControlledSampler{
samplerOptions: options, samplerOptions: options,
serviceName: serviceName, serviceName: serviceName,
timer: time.NewTicker(options.samplingRefreshInterval),
manager: &httpSamplingManager{serverURL: options.samplingServerURL}, manager: &httpSamplingManager{serverURL: options.samplingServerURL},
doneChan: make(chan *sync.WaitGroup),
} }
go sampler.pollController() go sampler.pollController()
return sampler return sampler
} }
@ -454,11 +452,15 @@ func (s *RemotelyControlledSampler) IsSampled(id TraceID, operation string) (boo
// Close implements Close() of Sampler. // Close implements Close() of Sampler.
func (s *RemotelyControlledSampler) Close() { func (s *RemotelyControlledSampler) Close() {
s.RLock() if swapped := atomic.CompareAndSwapInt64(&s.closed, 0, 1); !swapped {
s.timer.Stop() s.logger.Error("Repeated attempt to close the sampler is ignored")
s.RUnlock() return
}
s.pollStopped.Wait() var wg sync.WaitGroup
wg.Add(1)
s.doneChan <- &wg
wg.Wait()
} }
// Equal implements Equal() of Sampler. // Equal implements Equal() of Sampler.
@ -476,15 +478,33 @@ func (s *RemotelyControlledSampler) Equal(other Sampler) bool {
} }
func (s *RemotelyControlledSampler) pollController() { func (s *RemotelyControlledSampler) pollController() {
// in unit tests we re-assign the timer Ticker, so need to lock to avoid data races ticker := time.NewTicker(s.samplingRefreshInterval)
s.Lock() defer ticker.Stop()
timer := s.timer s.pollControllerWithTicker(ticker)
s.Unlock()
for range timer.C {
s.updateSampler()
} }
s.pollStopped.Add(1)
func (s *RemotelyControlledSampler) pollControllerWithTicker(ticker *time.Ticker) {
for {
select {
case <-ticker.C:
s.updateSampler()
case wg := <-s.doneChan:
wg.Done()
return
}
}
}
func (s *RemotelyControlledSampler) getSampler() Sampler {
s.Lock()
defer s.Unlock()
return s.sampler
}
func (s *RemotelyControlledSampler) setSampler(sampler Sampler) {
s.Lock()
defer s.Unlock()
s.sampler = sampler
} }
func (s *RemotelyControlledSampler) updateSampler() { func (s *RemotelyControlledSampler) updateSampler() {

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,27 +1,20 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017-2018 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package jaeger package jaeger
import ( import (
"strings"
"sync" "sync"
"time" "time"
@ -87,7 +80,7 @@ func (s *Span) SetOperationName(operationName string) opentracing.Span {
// SetTag implements SetTag() of opentracing.Span // SetTag implements SetTag() of opentracing.Span
func (s *Span) SetTag(key string, value interface{}) opentracing.Span { func (s *Span) SetTag(key string, value interface{}) opentracing.Span {
s.observer.OnSetTag(key, value) s.observer.OnSetTag(key, value)
if key == string(ext.SamplingPriority) && setSamplingPriority(s, value) { if key == string(ext.SamplingPriority) && !setSamplingPriority(s, value) {
return s return s
} }
s.Lock() s.Lock()
@ -167,24 +160,14 @@ func (s *Span) appendLog(lr opentracing.LogRecord) {
// SetBaggageItem implements SetBaggageItem() of opentracing.SpanContext // SetBaggageItem implements SetBaggageItem() of opentracing.SpanContext
func (s *Span) SetBaggageItem(key, value string) opentracing.Span { func (s *Span) SetBaggageItem(key, value string) opentracing.Span {
key = normalizeBaggageKey(key)
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
s.context = s.context.WithBaggageItem(key, value) s.tracer.setBaggage(s, key, value)
if s.context.IsSampled() {
// If sampled, record the baggage in the span
s.logFieldsNoLocking(
log.String("event", "baggage"),
log.String("key", key),
log.String("value", value),
)
}
return s return s
} }
// BaggageItem implements BaggageItem() of opentracing.SpanContext // BaggageItem implements BaggageItem() of opentracing.SpanContext
func (s *Span) BaggageItem(key string) string { func (s *Span) BaggageItem(key string) string {
key = normalizeBaggageKey(key)
s.RLock() s.RLock()
defer s.RUnlock() defer s.RUnlock()
return s.context.baggage[key] return s.context.baggage[key]
@ -219,6 +202,8 @@ func (s *Span) FinishWithOptions(options opentracing.FinishOptions) {
// Context implements opentracing.Span API // Context implements opentracing.Span API
func (s *Span) Context() opentracing.SpanContext { func (s *Span) Context() opentracing.SpanContext {
s.Lock()
defer s.Unlock()
return s.context return s.context
} }
@ -240,23 +225,25 @@ func (s *Span) OperationName() string {
return s.operationName return s.operationName
} }
func (s *Span) serviceName() string {
return s.tracer.serviceName
}
// setSamplingPriority returns true if the flag was updated successfully, false otherwise.
func setSamplingPriority(s *Span, value interface{}) bool { func setSamplingPriority(s *Span, value interface{}) bool {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
if val, ok := value.(uint16); ok { val, ok := value.(uint16)
if val > 0 { if !ok {
s.context.flags = s.context.flags | flagDebug | flagSampled return false
} else {
s.context.flags = s.context.flags & (^flagSampled)
} }
if val == 0 {
s.context.flags = s.context.flags & (^flagSampled)
return true
}
if s.tracer.isDebugAllowed(s.operationName) {
s.context.flags = s.context.flags | flagDebug | flagSampled
return true return true
} }
return false return false
} }
// Converts end-user baggage key into internal representation.
// Used for both read and write access to baggage items.
func normalizeBaggageKey(key string) string {
// TODO(yurishkuro) normalizeBaggageKey: cache the results in some bounded LRU cache
return strings.Replace(strings.ToLower(key), "_", "-", -1)
}

View file

@ -6,7 +6,7 @@ package agent
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
"github.com/uber/jaeger-client-go/thrift-gen/jaeger" "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore" "github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
) )
@ -16,6 +16,7 @@ var _ = thrift.ZERO
var _ = fmt.Printf var _ = fmt.Printf
var _ = bytes.Equal var _ = bytes.Equal
var _ = jaeger.GoUnusedProtection__
var _ = zipkincore.GoUnusedProtection__ var _ = zipkincore.GoUnusedProtection__
type Agent interface { type Agent interface {

View file

@ -6,7 +6,8 @@ package agent
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
"github.com/uber/jaeger-client-go/thrift-gen/jaeger"
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore" "github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
) )
@ -15,6 +16,7 @@ var _ = thrift.ZERO
var _ = fmt.Printf var _ = fmt.Printf
var _ = bytes.Equal var _ = bytes.Equal
var _ = jaeger.GoUnusedProtection__
var _ = zipkincore.GoUnusedProtection__ var _ = zipkincore.GoUnusedProtection__
func init() { func init() {

View file

@ -6,7 +6,8 @@ package agent
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
"github.com/uber/jaeger-client-go/thrift-gen/jaeger"
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore" "github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
) )
@ -15,5 +16,6 @@ var _ = thrift.ZERO
var _ = fmt.Printf var _ = fmt.Printf
var _ = bytes.Equal var _ = bytes.Equal
var _ = jaeger.GoUnusedProtection__
var _ = zipkincore.GoUnusedProtection__ var _ = zipkincore.GoUnusedProtection__
var GoUnusedProtection__ int var GoUnusedProtection__ int

View file

@ -0,0 +1,435 @@
// Autogenerated by Thrift Compiler (0.9.3)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package baggage
import (
"bytes"
"fmt"
"github.com/uber/jaeger-client-go/thrift"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = bytes.Equal
type BaggageRestrictionManager interface {
// getBaggageRestrictions retrieves the baggage restrictions for a specific service.
// Usually, baggageRestrictions apply to all services however there may be situations
// where a baggageKey might only be allowed to be set by a specific service.
//
// Parameters:
// - ServiceName
GetBaggageRestrictions(serviceName string) (r []*BaggageRestriction, err error)
}
type BaggageRestrictionManagerClient struct {
Transport thrift.TTransport
ProtocolFactory thrift.TProtocolFactory
InputProtocol thrift.TProtocol
OutputProtocol thrift.TProtocol
SeqId int32
}
func NewBaggageRestrictionManagerClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *BaggageRestrictionManagerClient {
return &BaggageRestrictionManagerClient{Transport: t,
ProtocolFactory: f,
InputProtocol: f.GetProtocol(t),
OutputProtocol: f.GetProtocol(t),
SeqId: 0,
}
}
func NewBaggageRestrictionManagerClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *BaggageRestrictionManagerClient {
return &BaggageRestrictionManagerClient{Transport: t,
ProtocolFactory: nil,
InputProtocol: iprot,
OutputProtocol: oprot,
SeqId: 0,
}
}
// getBaggageRestrictions retrieves the baggage restrictions for a specific service.
// Usually, baggageRestrictions apply to all services however there may be situations
// where a baggageKey might only be allowed to be set by a specific service.
//
// Parameters:
// - ServiceName
func (p *BaggageRestrictionManagerClient) GetBaggageRestrictions(serviceName string) (r []*BaggageRestriction, err error) {
if err = p.sendGetBaggageRestrictions(serviceName); err != nil {
return
}
return p.recvGetBaggageRestrictions()
}
func (p *BaggageRestrictionManagerClient) sendGetBaggageRestrictions(serviceName string) (err error) {
oprot := p.OutputProtocol
if oprot == nil {
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
p.OutputProtocol = oprot
}
p.SeqId++
if err = oprot.WriteMessageBegin("getBaggageRestrictions", thrift.CALL, p.SeqId); err != nil {
return
}
args := BaggageRestrictionManagerGetBaggageRestrictionsArgs{
ServiceName: serviceName,
}
if err = args.Write(oprot); err != nil {
return
}
if err = oprot.WriteMessageEnd(); err != nil {
return
}
return oprot.Flush()
}
func (p *BaggageRestrictionManagerClient) recvGetBaggageRestrictions() (value []*BaggageRestriction, err error) {
iprot := p.InputProtocol
if iprot == nil {
iprot = p.ProtocolFactory.GetProtocol(p.Transport)
p.InputProtocol = iprot
}
method, mTypeId, seqId, err := iprot.ReadMessageBegin()
if err != nil {
return
}
if method != "getBaggageRestrictions" {
err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "getBaggageRestrictions failed: wrong method name")
return
}
if p.SeqId != seqId {
err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "getBaggageRestrictions failed: out of sequence response")
return
}
if mTypeId == thrift.EXCEPTION {
error0 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
var error1 error
error1, err = error0.Read(iprot)
if err != nil {
return
}
if err = iprot.ReadMessageEnd(); err != nil {
return
}
err = error1
return
}
if mTypeId != thrift.REPLY {
err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "getBaggageRestrictions failed: invalid message type")
return
}
result := BaggageRestrictionManagerGetBaggageRestrictionsResult{}
if err = result.Read(iprot); err != nil {
return
}
if err = iprot.ReadMessageEnd(); err != nil {
return
}
value = result.GetSuccess()
return
}
type BaggageRestrictionManagerProcessor struct {
processorMap map[string]thrift.TProcessorFunction
handler BaggageRestrictionManager
}
func (p *BaggageRestrictionManagerProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
p.processorMap[key] = processor
}
func (p *BaggageRestrictionManagerProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
processor, ok = p.processorMap[key]
return processor, ok
}
func (p *BaggageRestrictionManagerProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
return p.processorMap
}
func NewBaggageRestrictionManagerProcessor(handler BaggageRestrictionManager) *BaggageRestrictionManagerProcessor {
self2 := &BaggageRestrictionManagerProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
self2.processorMap["getBaggageRestrictions"] = &baggageRestrictionManagerProcessorGetBaggageRestrictions{handler: handler}
return self2
}
func (p *BaggageRestrictionManagerProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
name, _, seqId, err := iprot.ReadMessageBegin()
if err != nil {
return false, err
}
if processor, ok := p.GetProcessorFunction(name); ok {
return processor.Process(seqId, iprot, oprot)
}
iprot.Skip(thrift.STRUCT)
iprot.ReadMessageEnd()
x3 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
x3.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush()
return false, x3
}
type baggageRestrictionManagerProcessorGetBaggageRestrictions struct {
handler BaggageRestrictionManager
}
func (p *baggageRestrictionManagerProcessorGetBaggageRestrictions) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
args := BaggageRestrictionManagerGetBaggageRestrictionsArgs{}
if err = args.Read(iprot); err != nil {
iprot.ReadMessageEnd()
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
oprot.WriteMessageBegin("getBaggageRestrictions", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush()
return false, err
}
iprot.ReadMessageEnd()
result := BaggageRestrictionManagerGetBaggageRestrictionsResult{}
var retval []*BaggageRestriction
var err2 error
if retval, err2 = p.handler.GetBaggageRestrictions(args.ServiceName); err2 != nil {
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing getBaggageRestrictions: "+err2.Error())
oprot.WriteMessageBegin("getBaggageRestrictions", thrift.EXCEPTION, seqId)
x.Write(oprot)
oprot.WriteMessageEnd()
oprot.Flush()
return true, err2
} else {
result.Success = retval
}
if err2 = oprot.WriteMessageBegin("getBaggageRestrictions", thrift.REPLY, seqId); err2 != nil {
err = err2
}
if err2 = result.Write(oprot); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
err = err2
}
if err2 = oprot.Flush(); err == nil && err2 != nil {
err = err2
}
if err != nil {
return
}
return true, err
}
// HELPER FUNCTIONS AND STRUCTURES
// Attributes:
// - ServiceName
type BaggageRestrictionManagerGetBaggageRestrictionsArgs struct {
ServiceName string `thrift:"serviceName,1" json:"serviceName"`
}
func NewBaggageRestrictionManagerGetBaggageRestrictionsArgs() *BaggageRestrictionManagerGetBaggageRestrictionsArgs {
return &BaggageRestrictionManagerGetBaggageRestrictionsArgs{}
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) GetServiceName() string {
return p.ServiceName
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if err := p.readField1(iprot); err != nil {
return err
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) readField1(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 1: ", err)
} else {
p.ServiceName = v
}
return nil
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("getBaggageRestrictions_args"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
}
if err := p.writeField1(oprot); err != nil {
return err
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err)
}
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err)
}
return nil
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("serviceName", thrift.STRING, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:serviceName: ", p), err)
}
if err := oprot.WriteString(string(p.ServiceName)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.serviceName (1) field write error: ", p), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:serviceName: ", p), err)
}
return err
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsArgs) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("BaggageRestrictionManagerGetBaggageRestrictionsArgs(%+v)", *p)
}
// Attributes:
// - Success
type BaggageRestrictionManagerGetBaggageRestrictionsResult struct {
Success []*BaggageRestriction `thrift:"success,0" json:"success,omitempty"`
}
func NewBaggageRestrictionManagerGetBaggageRestrictionsResult() *BaggageRestrictionManagerGetBaggageRestrictionsResult {
return &BaggageRestrictionManagerGetBaggageRestrictionsResult{}
}
var BaggageRestrictionManagerGetBaggageRestrictionsResult_Success_DEFAULT []*BaggageRestriction
func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) GetSuccess() []*BaggageRestriction {
return p.Success
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) IsSetSuccess() bool {
return p.Success != nil
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 0:
if err := p.readField0(iprot); err != nil {
return err
}
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
return nil
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) readField0(iprot thrift.TProtocol) error {
_, size, err := iprot.ReadListBegin()
if err != nil {
return thrift.PrependError("error reading list begin: ", err)
}
tSlice := make([]*BaggageRestriction, 0, size)
p.Success = tSlice
for i := 0; i < size; i++ {
_elem4 := &BaggageRestriction{}
if err := _elem4.Read(iprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err)
}
p.Success = append(p.Success, _elem4)
}
if err := iprot.ReadListEnd(); err != nil {
return thrift.PrependError("error reading list end: ", err)
}
return nil
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("getBaggageRestrictions_result"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
}
if err := p.writeField0(oprot); err != nil {
return err
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err)
}
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err)
}
return nil
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) writeField0(oprot thrift.TProtocol) (err error) {
if p.IsSetSuccess() {
if err := oprot.WriteFieldBegin("success", thrift.LIST, 0); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
}
if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Success)); err != nil {
return thrift.PrependError("error writing list begin: ", err)
}
for _, v := range p.Success {
if err := v.Write(oprot); err != nil {
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
}
}
if err := oprot.WriteListEnd(); err != nil {
return thrift.PrependError("error writing list end: ", err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
}
}
return err
}
func (p *BaggageRestrictionManagerGetBaggageRestrictionsResult) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("BaggageRestrictionManagerGetBaggageRestrictionsResult(%+v)", *p)
}

View file

@ -0,0 +1,18 @@
// Autogenerated by Thrift Compiler (0.9.3)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package baggage
import (
"bytes"
"fmt"
"github.com/uber/jaeger-client-go/thrift"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = bytes.Equal
func init() {
}

View file

@ -0,0 +1,154 @@
// Autogenerated by Thrift Compiler (0.9.3)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package baggage
import (
"bytes"
"fmt"
"github.com/uber/jaeger-client-go/thrift"
)
// (needed to ensure safety because of naive import list construction.)
var _ = thrift.ZERO
var _ = fmt.Printf
var _ = bytes.Equal
var GoUnusedProtection__ int
// Attributes:
// - BaggageKey
// - MaxValueLength
type BaggageRestriction struct {
BaggageKey string `thrift:"baggageKey,1,required" json:"baggageKey"`
MaxValueLength int32 `thrift:"maxValueLength,2,required" json:"maxValueLength"`
}
func NewBaggageRestriction() *BaggageRestriction {
return &BaggageRestriction{}
}
func (p *BaggageRestriction) GetBaggageKey() string {
return p.BaggageKey
}
func (p *BaggageRestriction) GetMaxValueLength() int32 {
return p.MaxValueLength
}
func (p *BaggageRestriction) Read(iprot thrift.TProtocol) error {
if _, err := iprot.ReadStructBegin(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
}
var issetBaggageKey bool = false
var issetMaxValueLength bool = false
for {
_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
if err != nil {
return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
}
if fieldTypeId == thrift.STOP {
break
}
switch fieldId {
case 1:
if err := p.readField1(iprot); err != nil {
return err
}
issetBaggageKey = true
case 2:
if err := p.readField2(iprot); err != nil {
return err
}
issetMaxValueLength = true
default:
if err := iprot.Skip(fieldTypeId); err != nil {
return err
}
}
if err := iprot.ReadFieldEnd(); err != nil {
return err
}
}
if err := iprot.ReadStructEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
}
if !issetBaggageKey {
return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field BaggageKey is not set"))
}
if !issetMaxValueLength {
return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field MaxValueLength is not set"))
}
return nil
}
func (p *BaggageRestriction) readField1(iprot thrift.TProtocol) error {
if v, err := iprot.ReadString(); err != nil {
return thrift.PrependError("error reading field 1: ", err)
} else {
p.BaggageKey = v
}
return nil
}
func (p *BaggageRestriction) readField2(iprot thrift.TProtocol) error {
if v, err := iprot.ReadI32(); err != nil {
return thrift.PrependError("error reading field 2: ", err)
} else {
p.MaxValueLength = v
}
return nil
}
func (p *BaggageRestriction) Write(oprot thrift.TProtocol) error {
if err := oprot.WriteStructBegin("BaggageRestriction"); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
}
if err := p.writeField1(oprot); err != nil {
return err
}
if err := p.writeField2(oprot); err != nil {
return err
}
if err := oprot.WriteFieldStop(); err != nil {
return thrift.PrependError("write field stop error: ", err)
}
if err := oprot.WriteStructEnd(); err != nil {
return thrift.PrependError("write struct stop error: ", err)
}
return nil
}
func (p *BaggageRestriction) writeField1(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("baggageKey", thrift.STRING, 1); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:baggageKey: ", p), err)
}
if err := oprot.WriteString(string(p.BaggageKey)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.baggageKey (1) field write error: ", p), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:baggageKey: ", p), err)
}
return err
}
func (p *BaggageRestriction) writeField2(oprot thrift.TProtocol) (err error) {
if err := oprot.WriteFieldBegin("maxValueLength", thrift.I32, 2); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:maxValueLength: ", p), err)
}
if err := oprot.WriteI32(int32(p.MaxValueLength)); err != nil {
return thrift.PrependError(fmt.Sprintf("%T.maxValueLength (2) field write error: ", p), err)
}
if err := oprot.WriteFieldEnd(); err != nil {
return thrift.PrependError(fmt.Sprintf("%T write field end error 2:maxValueLength: ", p), err)
}
return err
}
func (p *BaggageRestriction) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("BaggageRestriction(%+v)", *p)
}

View file

@ -6,7 +6,7 @@ package jaeger
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package jaeger
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package jaeger
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package sampling
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package sampling
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package sampling
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package zipkincore
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package zipkincore
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -6,7 +6,7 @@ package zipkincore
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
) )
// (needed to ensure safety because of naive import list construction.) // (needed to ensure safety because of naive import list construction.)

View file

@ -0,0 +1,142 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
const (
UNKNOWN_APPLICATION_EXCEPTION = 0
UNKNOWN_METHOD = 1
INVALID_MESSAGE_TYPE_EXCEPTION = 2
WRONG_METHOD_NAME = 3
BAD_SEQUENCE_ID = 4
MISSING_RESULT = 5
INTERNAL_ERROR = 6
PROTOCOL_ERROR = 7
)
// Application level Thrift exception
type TApplicationException interface {
TException
TypeId() int32
Read(iprot TProtocol) (TApplicationException, error)
Write(oprot TProtocol) error
}
type tApplicationException struct {
message string
type_ int32
}
func (e tApplicationException) Error() string {
return e.message
}
func NewTApplicationException(type_ int32, message string) TApplicationException {
return &tApplicationException{message, type_}
}
func (p *tApplicationException) TypeId() int32 {
return p.type_
}
func (p *tApplicationException) Read(iprot TProtocol) (TApplicationException, error) {
_, err := iprot.ReadStructBegin()
if err != nil {
return nil, err
}
message := ""
type_ := int32(UNKNOWN_APPLICATION_EXCEPTION)
for {
_, ttype, id, err := iprot.ReadFieldBegin()
if err != nil {
return nil, err
}
if ttype == STOP {
break
}
switch id {
case 1:
if ttype == STRING {
if message, err = iprot.ReadString(); err != nil {
return nil, err
}
} else {
if err = SkipDefaultDepth(iprot, ttype); err != nil {
return nil, err
}
}
case 2:
if ttype == I32 {
if type_, err = iprot.ReadI32(); err != nil {
return nil, err
}
} else {
if err = SkipDefaultDepth(iprot, ttype); err != nil {
return nil, err
}
}
default:
if err = SkipDefaultDepth(iprot, ttype); err != nil {
return nil, err
}
}
if err = iprot.ReadFieldEnd(); err != nil {
return nil, err
}
}
return NewTApplicationException(type_, message), iprot.ReadStructEnd()
}
func (p *tApplicationException) Write(oprot TProtocol) (err error) {
err = oprot.WriteStructBegin("TApplicationException")
if len(p.Error()) > 0 {
err = oprot.WriteFieldBegin("message", STRING, 1)
if err != nil {
return
}
err = oprot.WriteString(p.Error())
if err != nil {
return
}
err = oprot.WriteFieldEnd()
if err != nil {
return
}
}
err = oprot.WriteFieldBegin("type", I32, 2)
if err != nil {
return
}
err = oprot.WriteI32(p.type_)
if err != nil {
return
}
err = oprot.WriteFieldEnd()
if err != nil {
return
}
err = oprot.WriteFieldStop()
if err != nil {
return
}
err = oprot.WriteStructEnd()
return
}

View file

@ -0,0 +1,514 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"math"
)
type TBinaryProtocol struct {
trans TRichTransport
origTransport TTransport
reader io.Reader
writer io.Writer
strictRead bool
strictWrite bool
buffer [64]byte
}
type TBinaryProtocolFactory struct {
strictRead bool
strictWrite bool
}
func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol {
return NewTBinaryProtocol(t, false, true)
}
func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol {
p := &TBinaryProtocol{origTransport: t, strictRead: strictRead, strictWrite: strictWrite}
if et, ok := t.(TRichTransport); ok {
p.trans = et
} else {
p.trans = NewTRichTransport(t)
}
p.reader = p.trans
p.writer = p.trans
return p
}
func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory {
return NewTBinaryProtocolFactory(false, true)
}
func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory {
return &TBinaryProtocolFactory{strictRead: strictRead, strictWrite: strictWrite}
}
func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol {
return NewTBinaryProtocol(t, p.strictRead, p.strictWrite)
}
/**
* Writing Methods
*/
func (p *TBinaryProtocol) WriteMessageBegin(name string, typeId TMessageType, seqId int32) error {
if p.strictWrite {
version := uint32(VERSION_1) | uint32(typeId)
e := p.WriteI32(int32(version))
if e != nil {
return e
}
e = p.WriteString(name)
if e != nil {
return e
}
e = p.WriteI32(seqId)
return e
} else {
e := p.WriteString(name)
if e != nil {
return e
}
e = p.WriteByte(int8(typeId))
if e != nil {
return e
}
e = p.WriteI32(seqId)
return e
}
return nil
}
func (p *TBinaryProtocol) WriteMessageEnd() error {
return nil
}
func (p *TBinaryProtocol) WriteStructBegin(name string) error {
return nil
}
func (p *TBinaryProtocol) WriteStructEnd() error {
return nil
}
func (p *TBinaryProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
e := p.WriteByte(int8(typeId))
if e != nil {
return e
}
e = p.WriteI16(id)
return e
}
func (p *TBinaryProtocol) WriteFieldEnd() error {
return nil
}
func (p *TBinaryProtocol) WriteFieldStop() error {
e := p.WriteByte(STOP)
return e
}
func (p *TBinaryProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
e := p.WriteByte(int8(keyType))
if e != nil {
return e
}
e = p.WriteByte(int8(valueType))
if e != nil {
return e
}
e = p.WriteI32(int32(size))
return e
}
func (p *TBinaryProtocol) WriteMapEnd() error {
return nil
}
func (p *TBinaryProtocol) WriteListBegin(elemType TType, size int) error {
e := p.WriteByte(int8(elemType))
if e != nil {
return e
}
e = p.WriteI32(int32(size))
return e
}
func (p *TBinaryProtocol) WriteListEnd() error {
return nil
}
func (p *TBinaryProtocol) WriteSetBegin(elemType TType, size int) error {
e := p.WriteByte(int8(elemType))
if e != nil {
return e
}
e = p.WriteI32(int32(size))
return e
}
func (p *TBinaryProtocol) WriteSetEnd() error {
return nil
}
func (p *TBinaryProtocol) WriteBool(value bool) error {
if value {
return p.WriteByte(1)
}
return p.WriteByte(0)
}
func (p *TBinaryProtocol) WriteByte(value int8) error {
e := p.trans.WriteByte(byte(value))
return NewTProtocolException(e)
}
func (p *TBinaryProtocol) WriteI16(value int16) error {
v := p.buffer[0:2]
binary.BigEndian.PutUint16(v, uint16(value))
_, e := p.writer.Write(v)
return NewTProtocolException(e)
}
func (p *TBinaryProtocol) WriteI32(value int32) error {
v := p.buffer[0:4]
binary.BigEndian.PutUint32(v, uint32(value))
_, e := p.writer.Write(v)
return NewTProtocolException(e)
}
func (p *TBinaryProtocol) WriteI64(value int64) error {
v := p.buffer[0:8]
binary.BigEndian.PutUint64(v, uint64(value))
_, err := p.writer.Write(v)
return NewTProtocolException(err)
}
func (p *TBinaryProtocol) WriteDouble(value float64) error {
return p.WriteI64(int64(math.Float64bits(value)))
}
func (p *TBinaryProtocol) WriteString(value string) error {
e := p.WriteI32(int32(len(value)))
if e != nil {
return e
}
_, err := p.trans.WriteString(value)
return NewTProtocolException(err)
}
func (p *TBinaryProtocol) WriteBinary(value []byte) error {
e := p.WriteI32(int32(len(value)))
if e != nil {
return e
}
_, err := p.writer.Write(value)
return NewTProtocolException(err)
}
/**
* Reading methods
*/
func (p *TBinaryProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
size, e := p.ReadI32()
if e != nil {
return "", typeId, 0, NewTProtocolException(e)
}
if size < 0 {
typeId = TMessageType(size & 0x0ff)
version := int64(int64(size) & VERSION_MASK)
if version != VERSION_1 {
return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Bad version in ReadMessageBegin"))
}
name, e = p.ReadString()
if e != nil {
return name, typeId, seqId, NewTProtocolException(e)
}
seqId, e = p.ReadI32()
if e != nil {
return name, typeId, seqId, NewTProtocolException(e)
}
return name, typeId, seqId, nil
}
if p.strictRead {
return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin"))
}
name, e2 := p.readStringBody(size)
if e2 != nil {
return name, typeId, seqId, e2
}
b, e3 := p.ReadByte()
if e3 != nil {
return name, typeId, seqId, e3
}
typeId = TMessageType(b)
seqId, e4 := p.ReadI32()
if e4 != nil {
return name, typeId, seqId, e4
}
return name, typeId, seqId, nil
}
func (p *TBinaryProtocol) ReadMessageEnd() error {
return nil
}
func (p *TBinaryProtocol) ReadStructBegin() (name string, err error) {
return
}
func (p *TBinaryProtocol) ReadStructEnd() error {
return nil
}
func (p *TBinaryProtocol) ReadFieldBegin() (name string, typeId TType, seqId int16, err error) {
t, err := p.ReadByte()
typeId = TType(t)
if err != nil {
return name, typeId, seqId, err
}
if t != STOP {
seqId, err = p.ReadI16()
}
return name, typeId, seqId, err
}
func (p *TBinaryProtocol) ReadFieldEnd() error {
return nil
}
var invalidDataLength = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Invalid data length"))
func (p *TBinaryProtocol) ReadMapBegin() (kType, vType TType, size int, err error) {
k, e := p.ReadByte()
if e != nil {
err = NewTProtocolException(e)
return
}
kType = TType(k)
v, e := p.ReadByte()
if e != nil {
err = NewTProtocolException(e)
return
}
vType = TType(v)
size32, e := p.ReadI32()
if e != nil {
err = NewTProtocolException(e)
return
}
if size32 < 0 {
err = invalidDataLength
return
}
size = int(size32)
return kType, vType, size, nil
}
func (p *TBinaryProtocol) ReadMapEnd() error {
return nil
}
func (p *TBinaryProtocol) ReadListBegin() (elemType TType, size int, err error) {
b, e := p.ReadByte()
if e != nil {
err = NewTProtocolException(e)
return
}
elemType = TType(b)
size32, e := p.ReadI32()
if e != nil {
err = NewTProtocolException(e)
return
}
if size32 < 0 {
err = invalidDataLength
return
}
size = int(size32)
return
}
func (p *TBinaryProtocol) ReadListEnd() error {
return nil
}
func (p *TBinaryProtocol) ReadSetBegin() (elemType TType, size int, err error) {
b, e := p.ReadByte()
if e != nil {
err = NewTProtocolException(e)
return
}
elemType = TType(b)
size32, e := p.ReadI32()
if e != nil {
err = NewTProtocolException(e)
return
}
if size32 < 0 {
err = invalidDataLength
return
}
size = int(size32)
return elemType, size, nil
}
func (p *TBinaryProtocol) ReadSetEnd() error {
return nil
}
func (p *TBinaryProtocol) ReadBool() (bool, error) {
b, e := p.ReadByte()
v := true
if b != 1 {
v = false
}
return v, e
}
func (p *TBinaryProtocol) ReadByte() (int8, error) {
v, err := p.trans.ReadByte()
return int8(v), err
}
func (p *TBinaryProtocol) ReadI16() (value int16, err error) {
buf := p.buffer[0:2]
err = p.readAll(buf)
value = int16(binary.BigEndian.Uint16(buf))
return value, err
}
func (p *TBinaryProtocol) ReadI32() (value int32, err error) {
buf := p.buffer[0:4]
err = p.readAll(buf)
value = int32(binary.BigEndian.Uint32(buf))
return value, err
}
func (p *TBinaryProtocol) ReadI64() (value int64, err error) {
buf := p.buffer[0:8]
err = p.readAll(buf)
value = int64(binary.BigEndian.Uint64(buf))
return value, err
}
func (p *TBinaryProtocol) ReadDouble() (value float64, err error) {
buf := p.buffer[0:8]
err = p.readAll(buf)
value = math.Float64frombits(binary.BigEndian.Uint64(buf))
return value, err
}
func (p *TBinaryProtocol) ReadString() (value string, err error) {
size, e := p.ReadI32()
if e != nil {
return "", e
}
if size < 0 {
err = invalidDataLength
return
}
return p.readStringBody(size)
}
func (p *TBinaryProtocol) ReadBinary() ([]byte, error) {
size, e := p.ReadI32()
if e != nil {
return nil, e
}
if size < 0 {
return nil, invalidDataLength
}
if uint64(size) > p.trans.RemainingBytes() {
return nil, invalidDataLength
}
isize := int(size)
buf := make([]byte, isize)
_, err := io.ReadFull(p.trans, buf)
return buf, NewTProtocolException(err)
}
func (p *TBinaryProtocol) Flush() (err error) {
return NewTProtocolException(p.trans.Flush())
}
func (p *TBinaryProtocol) Skip(fieldType TType) (err error) {
return SkipDefaultDepth(p, fieldType)
}
func (p *TBinaryProtocol) Transport() TTransport {
return p.origTransport
}
func (p *TBinaryProtocol) readAll(buf []byte) error {
_, err := io.ReadFull(p.reader, buf)
return NewTProtocolException(err)
}
const readLimit = 32768
func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) {
if size < 0 {
return "", nil
}
if uint64(size) > p.trans.RemainingBytes() {
return "", invalidDataLength
}
var (
buf bytes.Buffer
e error
b []byte
)
switch {
case int(size) <= len(p.buffer):
b = p.buffer[:size] // avoids allocation for small reads
case int(size) < readLimit:
b = make([]byte, size)
default:
b = make([]byte, readLimit)
}
for size > 0 {
_, e = io.ReadFull(p.trans, b)
buf.Write(b)
if e != nil {
break
}
size -= readLimit
if size < readLimit && size > 0 {
b = b[:size]
}
}
return buf.String(), NewTProtocolException(e)
}

View file

@ -0,0 +1,815 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"encoding/binary"
"fmt"
"io"
"math"
)
const (
COMPACT_PROTOCOL_ID = 0x082
COMPACT_VERSION = 1
COMPACT_VERSION_MASK = 0x1f
COMPACT_TYPE_MASK = 0x0E0
COMPACT_TYPE_BITS = 0x07
COMPACT_TYPE_SHIFT_AMOUNT = 5
)
type tCompactType byte
const (
COMPACT_BOOLEAN_TRUE = 0x01
COMPACT_BOOLEAN_FALSE = 0x02
COMPACT_BYTE = 0x03
COMPACT_I16 = 0x04
COMPACT_I32 = 0x05
COMPACT_I64 = 0x06
COMPACT_DOUBLE = 0x07
COMPACT_BINARY = 0x08
COMPACT_LIST = 0x09
COMPACT_SET = 0x0A
COMPACT_MAP = 0x0B
COMPACT_STRUCT = 0x0C
)
var (
ttypeToCompactType map[TType]tCompactType
)
func init() {
ttypeToCompactType = map[TType]tCompactType{
STOP: STOP,
BOOL: COMPACT_BOOLEAN_TRUE,
BYTE: COMPACT_BYTE,
I16: COMPACT_I16,
I32: COMPACT_I32,
I64: COMPACT_I64,
DOUBLE: COMPACT_DOUBLE,
STRING: COMPACT_BINARY,
LIST: COMPACT_LIST,
SET: COMPACT_SET,
MAP: COMPACT_MAP,
STRUCT: COMPACT_STRUCT,
}
}
type TCompactProtocolFactory struct{}
func NewTCompactProtocolFactory() *TCompactProtocolFactory {
return &TCompactProtocolFactory{}
}
func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol {
return NewTCompactProtocol(trans)
}
type TCompactProtocol struct {
trans TRichTransport
origTransport TTransport
// Used to keep track of the last field for the current and previous structs,
// so we can do the delta stuff.
lastField []int
lastFieldId int
// If we encounter a boolean field begin, save the TField here so it can
// have the value incorporated.
booleanFieldName string
booleanFieldId int16
booleanFieldPending bool
// If we read a field header, and it's a boolean field, save the boolean
// value here so that readBool can use it.
boolValue bool
boolValueIsNotNull bool
buffer [64]byte
}
// Create a TCompactProtocol given a TTransport
func NewTCompactProtocol(trans TTransport) *TCompactProtocol {
p := &TCompactProtocol{origTransport: trans, lastField: []int{}}
if et, ok := trans.(TRichTransport); ok {
p.trans = et
} else {
p.trans = NewTRichTransport(trans)
}
return p
}
//
// Public Writing methods.
//
// Write a message header to the wire. Compact Protocol messages contain the
// protocol version so we can migrate forwards in the future if need be.
func (p *TCompactProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error {
err := p.writeByteDirect(COMPACT_PROTOCOL_ID)
if err != nil {
return NewTProtocolException(err)
}
err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK))
if err != nil {
return NewTProtocolException(err)
}
_, err = p.writeVarint32(seqid)
if err != nil {
return NewTProtocolException(err)
}
e := p.WriteString(name)
return e
}
func (p *TCompactProtocol) WriteMessageEnd() error { return nil }
// Write a struct begin. This doesn't actually put anything on the wire. We
// use it as an opportunity to put special placeholder markers on the field
// stack so we can get the field id deltas correct.
func (p *TCompactProtocol) WriteStructBegin(name string) error {
p.lastField = append(p.lastField, p.lastFieldId)
p.lastFieldId = 0
return nil
}
// Write a struct end. This doesn't actually put anything on the wire. We use
// this as an opportunity to pop the last field from the current struct off
// of the field stack.
func (p *TCompactProtocol) WriteStructEnd() error {
p.lastFieldId = p.lastField[len(p.lastField)-1]
p.lastField = p.lastField[:len(p.lastField)-1]
return nil
}
func (p *TCompactProtocol) WriteFieldBegin(name string, typeId TType, id int16) error {
if typeId == BOOL {
// we want to possibly include the value, so we'll wait.
p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true
return nil
}
_, err := p.writeFieldBeginInternal(name, typeId, id, 0xFF)
return NewTProtocolException(err)
}
// The workhorse of writeFieldBegin. It has the option of doing a
// 'type override' of the type header. This is used specifically in the
// boolean field case.
func (p *TCompactProtocol) writeFieldBeginInternal(name string, typeId TType, id int16, typeOverride byte) (int, error) {
// short lastField = lastField_.pop();
// if there's a type override, use that.
var typeToWrite byte
if typeOverride == 0xFF {
typeToWrite = byte(p.getCompactType(typeId))
} else {
typeToWrite = typeOverride
}
// check if we can use delta encoding for the field id
fieldId := int(id)
written := 0
if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 {
// write them together
err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite)
if err != nil {
return 0, err
}
} else {
// write them separate
err := p.writeByteDirect(typeToWrite)
if err != nil {
return 0, err
}
err = p.WriteI16(id)
written = 1 + 2
if err != nil {
return 0, err
}
}
p.lastFieldId = fieldId
// p.lastField.Push(field.id);
return written, nil
}
func (p *TCompactProtocol) WriteFieldEnd() error { return nil }
func (p *TCompactProtocol) WriteFieldStop() error {
err := p.writeByteDirect(STOP)
return NewTProtocolException(err)
}
func (p *TCompactProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error {
if size == 0 {
err := p.writeByteDirect(0)
return NewTProtocolException(err)
}
_, err := p.writeVarint32(int32(size))
if err != nil {
return NewTProtocolException(err)
}
err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType)))
return NewTProtocolException(err)
}
func (p *TCompactProtocol) WriteMapEnd() error { return nil }
// Write a list header.
func (p *TCompactProtocol) WriteListBegin(elemType TType, size int) error {
_, err := p.writeCollectionBegin(elemType, size)
return NewTProtocolException(err)
}
func (p *TCompactProtocol) WriteListEnd() error { return nil }
// Write a set header.
func (p *TCompactProtocol) WriteSetBegin(elemType TType, size int) error {
_, err := p.writeCollectionBegin(elemType, size)
return NewTProtocolException(err)
}
func (p *TCompactProtocol) WriteSetEnd() error { return nil }
func (p *TCompactProtocol) WriteBool(value bool) error {
v := byte(COMPACT_BOOLEAN_FALSE)
if value {
v = byte(COMPACT_BOOLEAN_TRUE)
}
if p.booleanFieldPending {
// we haven't written the field header yet
_, err := p.writeFieldBeginInternal(p.booleanFieldName, BOOL, p.booleanFieldId, v)
p.booleanFieldPending = false
return NewTProtocolException(err)
}
// we're not part of a field, so just write the value.
err := p.writeByteDirect(v)
return NewTProtocolException(err)
}
// Write a byte. Nothing to see here!
func (p *TCompactProtocol) WriteByte(value int8) error {
err := p.writeByteDirect(byte(value))
return NewTProtocolException(err)
}
// Write an I16 as a zigzag varint.
func (p *TCompactProtocol) WriteI16(value int16) error {
_, err := p.writeVarint32(p.int32ToZigzag(int32(value)))
return NewTProtocolException(err)
}
// Write an i32 as a zigzag varint.
func (p *TCompactProtocol) WriteI32(value int32) error {
_, err := p.writeVarint32(p.int32ToZigzag(value))
return NewTProtocolException(err)
}
// Write an i64 as a zigzag varint.
func (p *TCompactProtocol) WriteI64(value int64) error {
_, err := p.writeVarint64(p.int64ToZigzag(value))
return NewTProtocolException(err)
}
// Write a double to the wire as 8 bytes.
func (p *TCompactProtocol) WriteDouble(value float64) error {
buf := p.buffer[0:8]
binary.LittleEndian.PutUint64(buf, math.Float64bits(value))
_, err := p.trans.Write(buf)
return NewTProtocolException(err)
}
// Write a string to the wire with a varint size preceding.
func (p *TCompactProtocol) WriteString(value string) error {
_, e := p.writeVarint32(int32(len(value)))
if e != nil {
return NewTProtocolException(e)
}
if len(value) > 0 {
}
_, e = p.trans.WriteString(value)
return e
}
// Write a byte array, using a varint for the size.
func (p *TCompactProtocol) WriteBinary(bin []byte) error {
_, e := p.writeVarint32(int32(len(bin)))
if e != nil {
return NewTProtocolException(e)
}
if len(bin) > 0 {
_, e = p.trans.Write(bin)
return NewTProtocolException(e)
}
return nil
}
//
// Reading methods.
//
// Read a message header.
func (p *TCompactProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqId int32, err error) {
protocolId, err := p.readByteDirect()
if err != nil {
return
}
if protocolId != COMPACT_PROTOCOL_ID {
e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId)
return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e)
}
versionAndType, err := p.readByteDirect()
if err != nil {
return
}
version := versionAndType & COMPACT_VERSION_MASK
typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS)
if version != COMPACT_VERSION {
e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version)
err = NewTProtocolExceptionWithType(BAD_VERSION, e)
return
}
seqId, e := p.readVarint32()
if e != nil {
err = NewTProtocolException(e)
return
}
name, err = p.ReadString()
return
}
func (p *TCompactProtocol) ReadMessageEnd() error { return nil }
// Read a struct begin. There's nothing on the wire for this, but it is our
// opportunity to push a new struct begin marker onto the field stack.
func (p *TCompactProtocol) ReadStructBegin() (name string, err error) {
p.lastField = append(p.lastField, p.lastFieldId)
p.lastFieldId = 0
return
}
// Doesn't actually consume any wire data, just removes the last field for
// this struct from the field stack.
func (p *TCompactProtocol) ReadStructEnd() error {
// consume the last field we read off the wire.
p.lastFieldId = p.lastField[len(p.lastField)-1]
p.lastField = p.lastField[:len(p.lastField)-1]
return nil
}
// Read a field header off the wire.
func (p *TCompactProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) {
t, err := p.readByteDirect()
if err != nil {
return
}
// if it's a stop, then we can return immediately, as the struct is over.
if (t & 0x0f) == STOP {
return "", STOP, 0, nil
}
// mask off the 4 MSB of the type header. it could contain a field id delta.
modifier := int16((t & 0xf0) >> 4)
if modifier == 0 {
// not a delta. look ahead for the zigzag varint field id.
id, err = p.ReadI16()
if err != nil {
return
}
} else {
// has a delta. add the delta to the last read field id.
id = int16(p.lastFieldId) + modifier
}
typeId, e := p.getTType(tCompactType(t & 0x0f))
if e != nil {
err = NewTProtocolException(e)
return
}
// if this happens to be a boolean field, the value is encoded in the type
if p.isBoolType(t) {
// save the boolean value in a special instance variable.
p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE)
p.boolValueIsNotNull = true
}
// push the new field onto the field stack so we can keep the deltas going.
p.lastFieldId = int(id)
return
}
func (p *TCompactProtocol) ReadFieldEnd() error { return nil }
// Read a map header off the wire. If the size is zero, skip reading the key
// and value type. This means that 0-length maps will yield TMaps without the
// "correct" types.
func (p *TCompactProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) {
size32, e := p.readVarint32()
if e != nil {
err = NewTProtocolException(e)
return
}
if size32 < 0 {
err = invalidDataLength
return
}
size = int(size32)
keyAndValueType := byte(STOP)
if size != 0 {
keyAndValueType, err = p.readByteDirect()
if err != nil {
return
}
}
keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4))
valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf))
return
}
func (p *TCompactProtocol) ReadMapEnd() error { return nil }
// Read a list header off the wire. If the list size is 0-14, the size will
// be packed into the element type header. If it's a longer list, the 4 MSB
// of the element type header will be 0xF, and a varint will follow with the
// true size.
func (p *TCompactProtocol) ReadListBegin() (elemType TType, size int, err error) {
size_and_type, err := p.readByteDirect()
if err != nil {
return
}
size = int((size_and_type >> 4) & 0x0f)
if size == 15 {
size2, e := p.readVarint32()
if e != nil {
err = NewTProtocolException(e)
return
}
if size2 < 0 {
err = invalidDataLength
return
}
size = int(size2)
}
elemType, e := p.getTType(tCompactType(size_and_type))
if e != nil {
err = NewTProtocolException(e)
return
}
return
}
func (p *TCompactProtocol) ReadListEnd() error { return nil }
// Read a set header off the wire. If the set size is 0-14, the size will
// be packed into the element type header. If it's a longer set, the 4 MSB
// of the element type header will be 0xF, and a varint will follow with the
// true size.
func (p *TCompactProtocol) ReadSetBegin() (elemType TType, size int, err error) {
return p.ReadListBegin()
}
func (p *TCompactProtocol) ReadSetEnd() error { return nil }
// Read a boolean off the wire. If this is a boolean field, the value should
// already have been read during readFieldBegin, so we'll just consume the
// pre-stored value. Otherwise, read a byte.
func (p *TCompactProtocol) ReadBool() (value bool, err error) {
if p.boolValueIsNotNull {
p.boolValueIsNotNull = false
return p.boolValue, nil
}
v, err := p.readByteDirect()
return v == COMPACT_BOOLEAN_TRUE, err
}
// Read a single byte off the wire. Nothing interesting here.
func (p *TCompactProtocol) ReadByte() (int8, error) {
v, err := p.readByteDirect()
if err != nil {
return 0, NewTProtocolException(err)
}
return int8(v), err
}
// Read an i16 from the wire as a zigzag varint.
func (p *TCompactProtocol) ReadI16() (value int16, err error) {
v, err := p.ReadI32()
return int16(v), err
}
// Read an i32 from the wire as a zigzag varint.
func (p *TCompactProtocol) ReadI32() (value int32, err error) {
v, e := p.readVarint32()
if e != nil {
return 0, NewTProtocolException(e)
}
value = p.zigzagToInt32(v)
return value, nil
}
// Read an i64 from the wire as a zigzag varint.
func (p *TCompactProtocol) ReadI64() (value int64, err error) {
v, e := p.readVarint64()
if e != nil {
return 0, NewTProtocolException(e)
}
value = p.zigzagToInt64(v)
return value, nil
}
// No magic here - just read a double off the wire.
func (p *TCompactProtocol) ReadDouble() (value float64, err error) {
longBits := p.buffer[0:8]
_, e := io.ReadFull(p.trans, longBits)
if e != nil {
return 0.0, NewTProtocolException(e)
}
return math.Float64frombits(p.bytesToUint64(longBits)), nil
}
// Reads a []byte (via readBinary), and then UTF-8 decodes it.
func (p *TCompactProtocol) ReadString() (value string, err error) {
length, e := p.readVarint32()
if e != nil {
return "", NewTProtocolException(e)
}
if length < 0 {
return "", invalidDataLength
}
if uint64(length) > p.trans.RemainingBytes() {
return "", invalidDataLength
}
if length == 0 {
return "", nil
}
var buf []byte
if length <= int32(len(p.buffer)) {
buf = p.buffer[0:length]
} else {
buf = make([]byte, length)
}
_, e = io.ReadFull(p.trans, buf)
return string(buf), NewTProtocolException(e)
}
// Read a []byte from the wire.
func (p *TCompactProtocol) ReadBinary() (value []byte, err error) {
length, e := p.readVarint32()
if e != nil {
return nil, NewTProtocolException(e)
}
if length == 0 {
return []byte{}, nil
}
if length < 0 {
return nil, invalidDataLength
}
if uint64(length) > p.trans.RemainingBytes() {
return nil, invalidDataLength
}
buf := make([]byte, length)
_, e = io.ReadFull(p.trans, buf)
return buf, NewTProtocolException(e)
}
func (p *TCompactProtocol) Flush() (err error) {
return NewTProtocolException(p.trans.Flush())
}
func (p *TCompactProtocol) Skip(fieldType TType) (err error) {
return SkipDefaultDepth(p, fieldType)
}
func (p *TCompactProtocol) Transport() TTransport {
return p.origTransport
}
//
// Internal writing methods
//
// Abstract method for writing the start of lists and sets. List and sets on
// the wire differ only by the type indicator.
func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) {
if size <= 14 {
return 1, p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType))))
}
err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType)))
if err != nil {
return 0, err
}
m, err := p.writeVarint32(int32(size))
return 1 + m, err
}
// Write an i32 as a varint. Results in 1-5 bytes on the wire.
// TODO(pomack): make a permanent buffer like writeVarint64?
func (p *TCompactProtocol) writeVarint32(n int32) (int, error) {
i32buf := p.buffer[0:5]
idx := 0
for {
if (n & ^0x7F) == 0 {
i32buf[idx] = byte(n)
idx++
// p.writeByteDirect(byte(n));
break
// return;
} else {
i32buf[idx] = byte((n & 0x7F) | 0x80)
idx++
// p.writeByteDirect(byte(((n & 0x7F) | 0x80)));
u := uint32(n)
n = int32(u >> 7)
}
}
return p.trans.Write(i32buf[0:idx])
}
// Write an i64 as a varint. Results in 1-10 bytes on the wire.
func (p *TCompactProtocol) writeVarint64(n int64) (int, error) {
varint64out := p.buffer[0:10]
idx := 0
for {
if (n & ^0x7F) == 0 {
varint64out[idx] = byte(n)
idx++
break
} else {
varint64out[idx] = byte((n & 0x7F) | 0x80)
idx++
u := uint64(n)
n = int64(u >> 7)
}
}
return p.trans.Write(varint64out[0:idx])
}
// Convert l into a zigzag long. This allows negative numbers to be
// represented compactly as a varint.
func (p *TCompactProtocol) int64ToZigzag(l int64) int64 {
return (l << 1) ^ (l >> 63)
}
// Convert l into a zigzag long. This allows negative numbers to be
// represented compactly as a varint.
func (p *TCompactProtocol) int32ToZigzag(n int32) int32 {
return (n << 1) ^ (n >> 31)
}
func (p *TCompactProtocol) fixedUint64ToBytes(n uint64, buf []byte) {
binary.LittleEndian.PutUint64(buf, n)
}
func (p *TCompactProtocol) fixedInt64ToBytes(n int64, buf []byte) {
binary.LittleEndian.PutUint64(buf, uint64(n))
}
// Writes a byte without any possibility of all that field header nonsense.
// Used internally by other writing methods that know they need to write a byte.
func (p *TCompactProtocol) writeByteDirect(b byte) error {
return p.trans.WriteByte(b)
}
// Writes a byte without any possibility of all that field header nonsense.
func (p *TCompactProtocol) writeIntAsByteDirect(n int) (int, error) {
return 1, p.writeByteDirect(byte(n))
}
//
// Internal reading methods
//
// Read an i32 from the wire as a varint. The MSB of each byte is set
// if there is another byte to follow. This can read up to 5 bytes.
func (p *TCompactProtocol) readVarint32() (int32, error) {
// if the wire contains the right stuff, this will just truncate the i64 we
// read and get us the right sign.
v, err := p.readVarint64()
return int32(v), err
}
// Read an i64 from the wire as a proper varint. The MSB of each byte is set
// if there is another byte to follow. This can read up to 10 bytes.
func (p *TCompactProtocol) readVarint64() (int64, error) {
shift := uint(0)
result := int64(0)
for {
b, err := p.readByteDirect()
if err != nil {
return 0, err
}
result |= int64(b&0x7f) << shift
if (b & 0x80) != 0x80 {
break
}
shift += 7
}
return result, nil
}
// Read a byte, unlike ReadByte that reads Thrift-byte that is i8.
func (p *TCompactProtocol) readByteDirect() (byte, error) {
return p.trans.ReadByte()
}
//
// encoding helpers
//
// Convert from zigzag int to int.
func (p *TCompactProtocol) zigzagToInt32(n int32) int32 {
u := uint32(n)
return int32(u>>1) ^ -(n & 1)
}
// Convert from zigzag long to long.
func (p *TCompactProtocol) zigzagToInt64(n int64) int64 {
u := uint64(n)
return int64(u>>1) ^ -(n & 1)
}
// Note that it's important that the mask bytes are long literals,
// otherwise they'll default to ints, and when you shift an int left 56 bits,
// you just get a messed up int.
func (p *TCompactProtocol) bytesToInt64(b []byte) int64 {
return int64(binary.LittleEndian.Uint64(b))
}
// Note that it's important that the mask bytes are long literals,
// otherwise they'll default to ints, and when you shift an int left 56 bits,
// you just get a messed up int.
func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 {
return binary.LittleEndian.Uint64(b)
}
//
// type testing and converting
//
func (p *TCompactProtocol) isBoolType(b byte) bool {
return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE
}
// Given a tCompactType constant, convert it to its corresponding
// TType value.
func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) {
switch byte(t) & 0x0f {
case STOP:
return STOP, nil
case COMPACT_BOOLEAN_FALSE, COMPACT_BOOLEAN_TRUE:
return BOOL, nil
case COMPACT_BYTE:
return BYTE, nil
case COMPACT_I16:
return I16, nil
case COMPACT_I32:
return I32, nil
case COMPACT_I64:
return I64, nil
case COMPACT_DOUBLE:
return DOUBLE, nil
case COMPACT_BINARY:
return STRING, nil
case COMPACT_LIST:
return LIST, nil
case COMPACT_SET:
return SET, nil
case COMPACT_MAP:
return MAP, nil
case COMPACT_STRUCT:
return STRUCT, nil
}
return STOP, TException(fmt.Errorf("don't know what type: %d", t&0x0f))
}
// Given a TType value, find the appropriate TCompactProtocol.Types constant.
func (p *TCompactProtocol) getCompactType(t TType) tCompactType {
return ttypeToCompactType[t]
}

View file

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"errors"
)
// Generic Thrift exception
type TException interface {
error
}
// Prepends additional information to an error without losing the Thrift exception interface
func PrependError(prepend string, err error) error {
if t, ok := err.(TTransportException); ok {
return NewTTransportException(t.TypeId(), prepend+t.Error())
}
if t, ok := err.(TProtocolException); ok {
return NewTProtocolExceptionWithType(t.TypeId(), errors.New(prepend+err.Error()))
}
if t, ok := err.(TApplicationException); ok {
return NewTApplicationException(t.TypeId(), prepend+t.Error())
}
return errors.New(prepend + err.Error())
}

View file

@ -0,0 +1,79 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"bytes"
)
// Memory buffer-based implementation of the TTransport interface.
type TMemoryBuffer struct {
*bytes.Buffer
size int
}
type TMemoryBufferTransportFactory struct {
size int
}
func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) TTransport {
if trans != nil {
t, ok := trans.(*TMemoryBuffer)
if ok && t.size > 0 {
return NewTMemoryBufferLen(t.size)
}
}
return NewTMemoryBufferLen(p.size)
}
func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory {
return &TMemoryBufferTransportFactory{size: size}
}
func NewTMemoryBuffer() *TMemoryBuffer {
return &TMemoryBuffer{Buffer: &bytes.Buffer{}, size: 0}
}
func NewTMemoryBufferLen(size int) *TMemoryBuffer {
buf := make([]byte, 0, size)
return &TMemoryBuffer{Buffer: bytes.NewBuffer(buf), size: size}
}
func (p *TMemoryBuffer) IsOpen() bool {
return true
}
func (p *TMemoryBuffer) Open() error {
return nil
}
func (p *TMemoryBuffer) Close() error {
p.Buffer.Reset()
return nil
}
// Flushing a memory buffer is a no-op
func (p *TMemoryBuffer) Flush() error {
return nil
}
func (p *TMemoryBuffer) RemainingBytes() (num_bytes uint64) {
return uint64(p.Buffer.Len())
}

View file

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
// Message type constants in the Thrift protocol.
type TMessageType int32
const (
INVALID_TMESSAGE_TYPE TMessageType = 0
CALL TMessageType = 1
REPLY TMessageType = 2
EXCEPTION TMessageType = 3
ONEWAY TMessageType = 4
)

View file

@ -0,0 +1,164 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"math"
"strconv"
)
type Numeric interface {
Int64() int64
Int32() int32
Int16() int16
Byte() byte
Int() int
Float64() float64
Float32() float32
String() string
isNull() bool
}
type numeric struct {
iValue int64
dValue float64
sValue string
isNil bool
}
var (
INFINITY Numeric
NEGATIVE_INFINITY Numeric
NAN Numeric
ZERO Numeric
NUMERIC_NULL Numeric
)
func NewNumericFromDouble(dValue float64) Numeric {
if math.IsInf(dValue, 1) {
return INFINITY
}
if math.IsInf(dValue, -1) {
return NEGATIVE_INFINITY
}
if math.IsNaN(dValue) {
return NAN
}
iValue := int64(dValue)
sValue := strconv.FormatFloat(dValue, 'g', 10, 64)
isNil := false
return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
}
func NewNumericFromI64(iValue int64) Numeric {
dValue := float64(iValue)
sValue := string(iValue)
isNil := false
return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
}
func NewNumericFromI32(iValue int32) Numeric {
dValue := float64(iValue)
sValue := string(iValue)
isNil := false
return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil}
}
func NewNumericFromString(sValue string) Numeric {
if sValue == INFINITY.String() {
return INFINITY
}
if sValue == NEGATIVE_INFINITY.String() {
return NEGATIVE_INFINITY
}
if sValue == NAN.String() {
return NAN
}
iValue, _ := strconv.ParseInt(sValue, 10, 64)
dValue, _ := strconv.ParseFloat(sValue, 64)
isNil := len(sValue) == 0
return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil}
}
func NewNumericFromJSONString(sValue string, isNull bool) Numeric {
if isNull {
return NewNullNumeric()
}
if sValue == JSON_INFINITY {
return INFINITY
}
if sValue == JSON_NEGATIVE_INFINITY {
return NEGATIVE_INFINITY
}
if sValue == JSON_NAN {
return NAN
}
iValue, _ := strconv.ParseInt(sValue, 10, 64)
dValue, _ := strconv.ParseFloat(sValue, 64)
return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull}
}
func NewNullNumeric() Numeric {
return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true}
}
func (p *numeric) Int64() int64 {
return p.iValue
}
func (p *numeric) Int32() int32 {
return int32(p.iValue)
}
func (p *numeric) Int16() int16 {
return int16(p.iValue)
}
func (p *numeric) Byte() byte {
return byte(p.iValue)
}
func (p *numeric) Int() int {
return int(p.iValue)
}
func (p *numeric) Float64() float64 {
return p.dValue
}
func (p *numeric) Float32() float32 {
return float32(p.dValue)
}
func (p *numeric) String() string {
return p.sValue
}
func (p *numeric) isNull() bool {
return p.isNil
}
func init() {
INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false}
NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false}
NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false}
ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false}
NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true}
}

View file

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
// A processor is a generic object which operates upon an input stream and
// writes to some output stream.
type TProcessor interface {
Process(in, out TProtocol) (bool, TException)
}
type TProcessorFunction interface {
Process(seqId int32, in, out TProtocol) (bool, TException)
}

View file

@ -0,0 +1,175 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"errors"
)
const (
VERSION_MASK = 0xffff0000
VERSION_1 = 0x80010000
)
type TProtocol interface {
WriteMessageBegin(name string, typeId TMessageType, seqid int32) error
WriteMessageEnd() error
WriteStructBegin(name string) error
WriteStructEnd() error
WriteFieldBegin(name string, typeId TType, id int16) error
WriteFieldEnd() error
WriteFieldStop() error
WriteMapBegin(keyType TType, valueType TType, size int) error
WriteMapEnd() error
WriteListBegin(elemType TType, size int) error
WriteListEnd() error
WriteSetBegin(elemType TType, size int) error
WriteSetEnd() error
WriteBool(value bool) error
WriteByte(value int8) error
WriteI16(value int16) error
WriteI32(value int32) error
WriteI64(value int64) error
WriteDouble(value float64) error
WriteString(value string) error
WriteBinary(value []byte) error
ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error)
ReadMessageEnd() error
ReadStructBegin() (name string, err error)
ReadStructEnd() error
ReadFieldBegin() (name string, typeId TType, id int16, err error)
ReadFieldEnd() error
ReadMapBegin() (keyType TType, valueType TType, size int, err error)
ReadMapEnd() error
ReadListBegin() (elemType TType, size int, err error)
ReadListEnd() error
ReadSetBegin() (elemType TType, size int, err error)
ReadSetEnd() error
ReadBool() (value bool, err error)
ReadByte() (value int8, err error)
ReadI16() (value int16, err error)
ReadI32() (value int32, err error)
ReadI64() (value int64, err error)
ReadDouble() (value float64, err error)
ReadString() (value string, err error)
ReadBinary() (value []byte, err error)
Skip(fieldType TType) (err error)
Flush() (err error)
Transport() TTransport
}
// The maximum recursive depth the skip() function will traverse
const DEFAULT_RECURSION_DEPTH = 64
// Skips over the next data element from the provided input TProtocol object.
func SkipDefaultDepth(prot TProtocol, typeId TType) (err error) {
return Skip(prot, typeId, DEFAULT_RECURSION_DEPTH)
}
// Skips over the next data element from the provided input TProtocol object.
func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) {
if maxDepth <= 0 {
return NewTProtocolExceptionWithType( DEPTH_LIMIT, errors.New("Depth limit exceeded"))
}
switch fieldType {
case STOP:
return
case BOOL:
_, err = self.ReadBool()
return
case BYTE:
_, err = self.ReadByte()
return
case I16:
_, err = self.ReadI16()
return
case I32:
_, err = self.ReadI32()
return
case I64:
_, err = self.ReadI64()
return
case DOUBLE:
_, err = self.ReadDouble()
return
case STRING:
_, err = self.ReadString()
return
case STRUCT:
if _, err = self.ReadStructBegin(); err != nil {
return err
}
for {
_, typeId, _, _ := self.ReadFieldBegin()
if typeId == STOP {
break
}
err := Skip(self, typeId, maxDepth-1)
if err != nil {
return err
}
self.ReadFieldEnd()
}
return self.ReadStructEnd()
case MAP:
keyType, valueType, size, err := self.ReadMapBegin()
if err != nil {
return err
}
for i := 0; i < size; i++ {
err := Skip(self, keyType, maxDepth-1)
if err != nil {
return err
}
self.Skip(valueType)
}
return self.ReadMapEnd()
case SET:
elemType, size, err := self.ReadSetBegin()
if err != nil {
return err
}
for i := 0; i < size; i++ {
err := Skip(self, elemType, maxDepth-1)
if err != nil {
return err
}
}
return self.ReadSetEnd()
case LIST:
elemType, size, err := self.ReadListBegin()
if err != nil {
return err
}
for i := 0; i < size; i++ {
err := Skip(self, elemType, maxDepth-1)
if err != nil {
return err
}
}
return self.ReadListEnd()
}
return nil
}

View file

@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"encoding/base64"
)
// Thrift Protocol exception
type TProtocolException interface {
TException
TypeId() int
}
const (
UNKNOWN_PROTOCOL_EXCEPTION = 0
INVALID_DATA = 1
NEGATIVE_SIZE = 2
SIZE_LIMIT = 3
BAD_VERSION = 4
NOT_IMPLEMENTED = 5
DEPTH_LIMIT = 6
)
type tProtocolException struct {
typeId int
message string
}
func (p *tProtocolException) TypeId() int {
return p.typeId
}
func (p *tProtocolException) String() string {
return p.message
}
func (p *tProtocolException) Error() string {
return p.message
}
func NewTProtocolException(err error) TProtocolException {
if err == nil {
return nil
}
if e,ok := err.(TProtocolException); ok {
return e
}
if _, ok := err.(base64.CorruptInputError); ok {
return &tProtocolException{INVALID_DATA, err.Error()}
}
return &tProtocolException{UNKNOWN_PROTOCOL_EXCEPTION, err.Error()}
}
func NewTProtocolExceptionWithType(errType int, err error) TProtocolException {
if err == nil {
return nil
}
return &tProtocolException{errType, err.Error()}
}

View file

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
// Factory interface for constructing protocol instances.
type TProtocolFactory interface {
GetProtocol(trans TTransport) TProtocol
}

View file

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import "io"
type RichTransport struct {
TTransport
}
// Wraps Transport to provide TRichTransport interface
func NewTRichTransport(trans TTransport) *RichTransport {
return &RichTransport{trans}
}
func (r *RichTransport) ReadByte() (c byte, err error) {
return readByte(r.TTransport)
}
func (r *RichTransport) WriteByte(c byte) error {
return writeByte(r.TTransport, c)
}
func (r *RichTransport) WriteString(s string) (n int, err error) {
return r.Write([]byte(s))
}
func (r *RichTransport) RemainingBytes() (num_bytes uint64) {
return r.TTransport.RemainingBytes()
}
func readByte(r io.Reader) (c byte, err error) {
v := [1]byte{0}
n, err := r.Read(v[0:1])
if n > 0 && (err == nil || err == io.EOF) {
return v[0], nil
}
if n > 0 && err != nil {
return v[0], err
}
if err != nil {
return 0, err
}
return v[0], nil
}
func writeByte(w io.Writer, c byte) error {
v := [1]byte{c}
_, err := w.Write(v[0:1])
return err
}

View file

@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
type TSerializer struct {
Transport *TMemoryBuffer
Protocol TProtocol
}
type TStruct interface {
Write(p TProtocol) error
Read(p TProtocol) error
}
func NewTSerializer() *TSerializer {
transport := NewTMemoryBufferLen(1024)
protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport)
return &TSerializer{
transport,
protocol}
}
func (t *TSerializer) WriteString(msg TStruct) (s string, err error) {
t.Transport.Reset()
if err = msg.Write(t.Protocol); err != nil {
return
}
if err = t.Protocol.Flush(); err != nil {
return
}
if err = t.Transport.Flush(); err != nil {
return
}
return t.Transport.String(), nil
}
func (t *TSerializer) Write(msg TStruct) (b []byte, err error) {
t.Transport.Reset()
if err = msg.Write(t.Protocol); err != nil {
return
}
if err = t.Protocol.Flush(); err != nil {
return
}
if err = t.Transport.Flush(); err != nil {
return
}
b = append(b, t.Transport.Bytes()...)
return
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"errors"
"io"
)
var errTransportInterrupted = errors.New("Transport Interrupted")
type Flusher interface {
Flush() (err error)
}
type ReadSizeProvider interface {
RemainingBytes() (num_bytes uint64)
}
// Encapsulates the I/O layer
type TTransport interface {
io.ReadWriteCloser
Flusher
ReadSizeProvider
// Opens the transport for communication
Open() error
// Returns true if the transport is open
IsOpen() bool
}
type stringWriter interface {
WriteString(s string) (n int, err error)
}
// This is "enchanced" transport with extra capabilities. You need to use one of these
// to construct protocol.
// Notably, TSocket does not implement this interface, and it is always a mistake to use
// TSocket directly in protocol.
type TRichTransport interface {
io.ReadWriter
io.ByteReader
io.ByteWriter
stringWriter
Flusher
ReadSizeProvider
}

View file

@ -0,0 +1,90 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
import (
"errors"
"io"
)
type timeoutable interface {
Timeout() bool
}
// Thrift Transport exception
type TTransportException interface {
TException
TypeId() int
Err() error
}
const (
UNKNOWN_TRANSPORT_EXCEPTION = 0
NOT_OPEN = 1
ALREADY_OPEN = 2
TIMED_OUT = 3
END_OF_FILE = 4
)
type tTransportException struct {
typeId int
err error
}
func (p *tTransportException) TypeId() int {
return p.typeId
}
func (p *tTransportException) Error() string {
return p.err.Error()
}
func (p *tTransportException) Err() error {
return p.err
}
func NewTTransportException(t int, e string) TTransportException {
return &tTransportException{typeId: t, err: errors.New(e)}
}
func NewTTransportExceptionFromError(e error) TTransportException {
if e == nil {
return nil
}
if t, ok := e.(TTransportException); ok {
return t
}
switch v := e.(type) {
case TTransportException:
return v
case timeoutable:
if v.Timeout() {
return &tTransportException{typeId: TIMED_OUT, err: e}
}
}
if e == io.EOF {
return &tTransportException{typeId: END_OF_FILE, err: e}
}
return &tTransportException{typeId: UNKNOWN_TRANSPORT_EXCEPTION, err: e}
}

View file

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
// Factory class used to create wrapped instance of Transports.
// This is used primarily in servers, which get Transports from
// a ServerTransport and then may want to mutate them (i.e. create
// a BufferedTransport from the underlying base transport)
type TTransportFactory interface {
GetTransport(trans TTransport) TTransport
}
type tTransportFactory struct{}
// Return a wrapped instance of the base Transport.
func (p *tTransportFactory) GetTransport(trans TTransport) TTransport {
return trans
}
func NewTTransportFactory() TTransportFactory {
return &tTransportFactory{}
}

69
vendor/github.com/uber/jaeger-client-go/thrift/type.go generated vendored Normal file
View file

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package thrift
// Type constants in the Thrift protocol
type TType byte
const (
STOP = 0
VOID = 1
BOOL = 2
BYTE = 3
I08 = 3
DOUBLE = 4
I16 = 6
I32 = 8
I64 = 10
STRING = 11
UTF7 = 11
STRUCT = 12
MAP = 13
SET = 14
LIST = 15
UTF8 = 16
UTF16 = 17
//BINARY = 18 wrong and unusued
)
var typeNames = map[int]string{
STOP: "STOP",
VOID: "VOID",
BOOL: "BOOL",
BYTE: "BYTE",
DOUBLE: "DOUBLE",
I16: "I16",
I32: "I32",
I64: "I64",
STRING: "STRING",
STRUCT: "STRUCT",
MAP: "MAP",
SET: "SET",
LIST: "LIST",
UTF8: "UTF8",
UTF16: "UTF16",
}
func (p TType) String() string {
if s, ok := typeNames[int(p)]; ok {
return s
}
return "Unknown"
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017-2018 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package jaeger package jaeger
@ -25,12 +19,15 @@ import (
"io" "io"
"os" "os"
"reflect" "reflect"
"strconv"
"sync" "sync"
"time" "time"
"github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext" "github.com/opentracing/opentracing-go/ext"
"github.com/uber/jaeger-client-go/internal/baggage"
"github.com/uber/jaeger-client-go/internal/throttler"
"github.com/uber/jaeger-client-go/log" "github.com/uber/jaeger-client-go/log"
"github.com/uber/jaeger-client-go/utils" "github.com/uber/jaeger-client-go/utils"
) )
@ -52,6 +49,7 @@ type Tracer struct {
poolSpans bool poolSpans bool
gen128Bit bool // whether to generate 128bit trace IDs gen128Bit bool // whether to generate 128bit trace IDs
zipkinSharedRPCSpan bool zipkinSharedRPCSpan bool
highTraceIDGenerator func() uint64 // custom high trace ID generator
// more options to come // more options to come
} }
// pool for Span objects // pool for Span objects
@ -63,6 +61,12 @@ type Tracer struct {
observer compositeObserver observer compositeObserver
tags []Tag tags []Tag
process Process
baggageRestrictionManager baggage.RestrictionManager
baggageSetter *baggageSetter
debugThrottler throttler.Throttler
} }
// NewTracer creates Tracer implementation that reports tracing to Jaeger. // NewTracer creates Tracer implementation that reports tracing to Jaeger.
@ -86,30 +90,34 @@ func NewTracer(
}}, }},
} }
// register default injectors/extractors for _, option := range options {
textPropagator := newTextMapPropagator(t) option(t)
t.injectors[opentracing.TextMap] = textPropagator }
t.extractors[opentracing.TextMap] = textPropagator
httpHeaderPropagator := newHTTPHeaderPropagator(t) // register default injectors/extractors unless they are already provided via options
t.injectors[opentracing.HTTPHeaders] = httpHeaderPropagator textPropagator := newTextMapPropagator(getDefaultHeadersConfig(), t.metrics)
t.extractors[opentracing.HTTPHeaders] = httpHeaderPropagator t.addCodec(opentracing.TextMap, textPropagator, textPropagator)
httpHeaderPropagator := newHTTPHeaderPropagator(getDefaultHeadersConfig(), t.metrics)
t.addCodec(opentracing.HTTPHeaders, httpHeaderPropagator, httpHeaderPropagator)
binaryPropagator := newBinaryPropagator(t) binaryPropagator := newBinaryPropagator(t)
t.injectors[opentracing.Binary] = binaryPropagator t.addCodec(opentracing.Binary, binaryPropagator, binaryPropagator)
t.extractors[opentracing.Binary] = binaryPropagator
// TODO remove after TChannel supports OpenTracing // TODO remove after TChannel supports OpenTracing
interopPropagator := &jaegerTraceContextPropagator{tracer: t} interopPropagator := &jaegerTraceContextPropagator{tracer: t}
t.injectors[SpanContextFormat] = interopPropagator t.addCodec(SpanContextFormat, interopPropagator, interopPropagator)
t.extractors[SpanContextFormat] = interopPropagator
zipkinPropagator := &zipkinPropagator{tracer: t} zipkinPropagator := &zipkinPropagator{tracer: t}
t.injectors[ZipkinSpanFormat] = zipkinPropagator t.addCodec(ZipkinSpanFormat, zipkinPropagator, zipkinPropagator)
t.extractors[ZipkinSpanFormat] = zipkinPropagator
for _, option := range options { if t.baggageRestrictionManager != nil {
option(t) t.baggageSetter = newBaggageSetter(t.baggageRestrictionManager, &t.metrics)
} else {
t.baggageSetter = newBaggageSetter(baggage.NewDefaultRestrictionManager(0), &t.metrics)
}
if t.debugThrottler == nil {
t.debugThrottler = throttler.DefaultThrottler{}
} }
if t.randomNumber == nil { if t.randomNumber == nil {
@ -136,9 +144,36 @@ func NewTracer(
t.logger.Error("Unable to determine this host's IP address: " + err.Error()) t.logger.Error("Unable to determine this host's IP address: " + err.Error())
} }
if t.options.gen128Bit {
if t.options.highTraceIDGenerator == nil {
t.options.highTraceIDGenerator = t.randomNumber
}
} else if t.options.highTraceIDGenerator != nil {
t.logger.Error("Overriding high trace ID generator but not generating " +
"128 bit trace IDs, consider enabling the \"Gen128Bit\" option")
}
t.process = Process{
Service: serviceName,
UUID: strconv.FormatUint(t.randomNumber(), 16),
Tags: t.tags,
}
if throttler, ok := t.debugThrottler.(ProcessSetter); ok {
throttler.SetProcess(t.process)
}
return t, t return t, t
} }
// addCodec adds registers injector and extractor for given propagation format if not already defined.
func (t *Tracer) addCodec(format interface{}, injector Injector, extractor Extractor) {
if _, ok := t.injectors[format]; !ok {
t.injectors[format] = injector
}
if _, ok := t.extractors[format]; !ok {
t.extractors[format] = extractor
}
}
// StartSpan implements StartSpan() method of opentracing.Tracer. // StartSpan implements StartSpan() method of opentracing.Tracer.
func (t *Tracer) StartSpan( func (t *Tracer) StartSpan(
operationName string, operationName string,
@ -197,12 +232,12 @@ func (t *Tracer) startSpanWithOptions(
newTrace = true newTrace = true
ctx.traceID.Low = t.randomID() ctx.traceID.Low = t.randomID()
if t.options.gen128Bit { if t.options.gen128Bit {
ctx.traceID.High = t.randomID() ctx.traceID.High = t.options.highTraceIDGenerator()
} }
ctx.spanID = SpanID(ctx.traceID.Low) ctx.spanID = SpanID(ctx.traceID.Low)
ctx.parentID = 0 ctx.parentID = 0
ctx.flags = byte(0) ctx.flags = byte(0)
if hasParent && parent.isDebugIDContainerOnly() { if hasParent && parent.isDebugIDContainerOnly() && t.isDebugAllowed(operationName) {
ctx.flags |= (flagSampled | flagDebug) ctx.flags |= (flagSampled | flagDebug)
samplerTags = []Tag{{key: JaegerDebugHeader, value: parent.debugID}} samplerTags = []Tag{{key: JaegerDebugHeader, value: parent.debugID}}
} else if sampled, tags := t.sampler.IsSampled(ctx.traceID, operationName); sampled { } else if sampled, tags := t.sampler.IsSampled(ctx.traceID, operationName); sampled {
@ -273,6 +308,12 @@ func (t *Tracer) Extract(
func (t *Tracer) Close() error { func (t *Tracer) Close() error {
t.reporter.Close() t.reporter.Close()
t.sampler.Close() t.sampler.Close()
if mgr, ok := t.baggageRestrictionManager.(io.Closer); ok {
mgr.Close()
}
if throttler, ok := t.debugThrottler.(io.Closer); ok {
throttler.Close()
}
return nil return nil
} }
@ -320,16 +361,15 @@ func (t *Tracer) startSpanInternal(
copy(sp.tags, internalTags) copy(sp.tags, internalTags)
for k, v := range tags { for k, v := range tags {
sp.observer.OnSetTag(k, v) sp.observer.OnSetTag(k, v)
if k == string(ext.SamplingPriority) && setSamplingPriority(sp, v) { if k == string(ext.SamplingPriority) && !setSamplingPriority(sp, v) {
continue continue
} }
sp.setTagNoLocking(k, v) sp.setTagNoLocking(k, v)
} }
} }
// emit metrics // emit metrics
t.metrics.SpansStarted.Inc(1)
if sp.context.IsSampled() { if sp.context.IsSampled() {
t.metrics.SpansSampled.Inc(1) t.metrics.SpansStartedSampled.Inc(1)
if newTrace { if newTrace {
// We cannot simply check for parentID==0 because in Zipkin model the // We cannot simply check for parentID==0 because in Zipkin model the
// server-side RPC span has the exact same trace/span/parent IDs as the // server-side RPC span has the exact same trace/span/parent IDs as the
@ -340,7 +380,7 @@ func (t *Tracer) startSpanInternal(
t.metrics.TracesJoinedSampled.Inc(1) t.metrics.TracesJoinedSampled.Inc(1)
} }
} else { } else {
t.metrics.SpansNotSampled.Inc(1) t.metrics.SpansStartedNotSampled.Inc(1)
if newTrace { if newTrace {
t.metrics.TracesStartedNotSampled.Inc(1) t.metrics.TracesStartedNotSampled.Inc(1)
} else if sp.firstInProcess { } else if sp.firstInProcess {
@ -369,3 +409,13 @@ func (t *Tracer) randomID() uint64 {
} }
return val return val
} }
// (NB) span must hold the lock before making this call
func (t *Tracer) setBaggage(sp *Span, key, value string) {
t.baggageSetter.setBaggage(sp, key, value)
}
// (NB) span must hold the lock before making this call
func (t *Tracer) isDebugAllowed(operation string) bool {
return t.debugThrottler.IsAllowed(operation)
}

View file

@ -1,27 +1,26 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger
import ( import (
"time" "time"
"github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go/internal/baggage"
"github.com/uber/jaeger-client-go/internal/throttler"
) )
// TracerOption is a function that sets some option on the tracer // TracerOption is a function that sets some option on the tracer
@ -47,6 +46,19 @@ func (tracerOptions) Logger(logger Logger) TracerOption {
} }
} }
func (tracerOptions) CustomHeaderKeys(headerKeys *HeadersConfig) TracerOption {
return func(tracer *Tracer) {
if headerKeys == nil {
return
}
textPropagator := newTextMapPropagator(headerKeys.applyDefaults(), tracer.metrics)
tracer.addCodec(opentracing.TextMap, textPropagator, textPropagator)
httpHeaderPropagator := newHTTPHeaderPropagator(headerKeys.applyDefaults(), tracer.metrics)
tracer.addCodec(opentracing.HTTPHeaders, httpHeaderPropagator, httpHeaderPropagator)
}
}
// TimeNow creates a TracerOption that gives the tracer a function // TimeNow creates a TracerOption that gives the tracer a function
// used to generate timestamps for spans. // used to generate timestamps for spans.
func (tracerOptions) TimeNow(timeNow func() time.Time) TracerOption { func (tracerOptions) TimeNow(timeNow func() time.Time) TracerOption {
@ -104,6 +116,18 @@ func (tracerOptions) ContribObserver(observer ContribObserver) TracerOption {
} }
} }
func (tracerOptions) Gen128Bit(gen128Bit bool) TracerOption {
return func(tracer *Tracer) {
tracer.options.gen128Bit = gen128Bit
}
}
func (tracerOptions) HighTraceIDGenerator(highTraceIDGenerator func() uint64) TracerOption {
return func(tracer *Tracer) {
tracer.options.highTraceIDGenerator = highTraceIDGenerator
}
}
func (tracerOptions) ZipkinSharedRPCSpan(zipkinSharedRPCSpan bool) TracerOption { func (tracerOptions) ZipkinSharedRPCSpan(zipkinSharedRPCSpan bool) TracerOption {
return func(tracer *Tracer) { return func(tracer *Tracer) {
tracer.options.zipkinSharedRPCSpan = zipkinSharedRPCSpan tracer.options.zipkinSharedRPCSpan = zipkinSharedRPCSpan
@ -115,3 +139,15 @@ func (tracerOptions) Tag(key string, value interface{}) TracerOption {
tracer.tags = append(tracer.tags, Tag{key: key, value: value}) tracer.tags = append(tracer.tags, Tag{key: key, value: value})
} }
} }
func (tracerOptions) BaggageRestrictionManager(mgr baggage.RestrictionManager) TracerOption {
return func(tracer *Tracer) {
tracer.baggageRestrictionManager = mgr
}
}
func (tracerOptions) DebugThrottler(throttler throttler.Throttler) TracerOption {
return func(tracer *Tracer) {
tracer.debugThrottler = throttler
}
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -1,29 +1,24 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger
import ( import (
"errors" "errors"
"fmt"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
j "github.com/uber/jaeger-client-go/thrift-gen/jaeger" j "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
"github.com/uber/jaeger-client-go/utils" "github.com/uber/jaeger-client-go/utils"
@ -37,8 +32,6 @@ import (
// in the batch, because the length of the list is encoded as varint32, as well as SeqId. // in the batch, because the length of the list is encoded as varint32, as well as SeqId.
const emitBatchOverhead = 30 const emitBatchOverhead = 30
const defaultUDPSpanServerHostPort = "localhost:6831"
var errSpanTooLarge = errors.New("Span is too large") var errSpanTooLarge = errors.New("Span is too large")
type udpSender struct { type udpSender struct {
@ -56,7 +49,7 @@ type udpSender struct {
// NewUDPTransport creates a reporter that submits spans to jaeger-agent // NewUDPTransport creates a reporter that submits spans to jaeger-agent
func NewUDPTransport(hostPort string, maxPacketSize int) (Transport, error) { func NewUDPTransport(hostPort string, maxPacketSize int) (Transport, error) {
if len(hostPort) == 0 { if len(hostPort) == 0 {
hostPort = defaultUDPSpanServerHostPort hostPort = fmt.Sprintf("%s:%d", DefaultUDPSpanServerHost, DefaultUDPSpanServerPort)
} }
if maxPacketSize == 0 { if maxPacketSize == 0 {
maxPacketSize = utils.UDPPacketMaxLength maxPacketSize = utils.UDPPacketMaxLength

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package utils package utils

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package utils package utils

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package utils package utils

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package utils package utils

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package utils package utils
@ -26,7 +20,7 @@ import (
"io" "io"
"net" "net"
"github.com/apache/thrift/lib/go/thrift" "github.com/uber/jaeger-client-go/thrift"
"github.com/uber/jaeger-client-go/thrift-gen/agent" "github.com/uber/jaeger-client-go/thrift-gen/agent"
"github.com/uber/jaeger-client-go/thrift-gen/jaeger" "github.com/uber/jaeger-client-go/thrift-gen/jaeger"

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// 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:
// //
// The above copyright notice and this permission notice shall be included in // Licensed under the Apache License, Version 2.0 (the "License");
// all copies or substantial portions of the Software. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // http://www.apache.org/licenses/LICENSE-2.0
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // Unless required by applicable law or agreed to in writing, software
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // distributed under the License is distributed on an "AS IS" BASIS,
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // See the License for the specific language governing permissions and
// THE SOFTWARE. // limitations under the License.
package utils package utils

View file

@ -1,22 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

16
vendor/github.com/uber/jaeger-client-go/zipkin/doc.go generated vendored Normal file
View file

@ -0,0 +1,16 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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.
// Package zipkin comprises Zipkin functionality for Zipkin compatiblity.
package zipkin

View file

@ -0,0 +1,95 @@
// Copyright (c) 2017 Uber Technologies, Inc.
//
// 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.
package zipkin
import (
"strconv"
"strings"
opentracing "github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go"
)
// Propagator is an Injector and Extractor
type Propagator struct{}
// NewZipkinB3HTTPHeaderPropagator creates a Propagator for extracting and injecting
// Zipkin HTTP B3 headers into SpanContexts.
func NewZipkinB3HTTPHeaderPropagator() Propagator {
return Propagator{}
}
// Inject conforms to the Injector interface for decoding Zipkin HTTP B3 headers
func (p Propagator) Inject(
sc jaeger.SpanContext,
abstractCarrier interface{},
) error {
textMapWriter, ok := abstractCarrier.(opentracing.TextMapWriter)
if !ok {
return opentracing.ErrInvalidCarrier
}
// TODO this needs to change to support 128bit IDs
textMapWriter.Set("x-b3-traceid", strconv.FormatUint(sc.TraceID().Low, 16))
if sc.ParentID() != 0 {
textMapWriter.Set("x-b3-parentspanid", strconv.FormatUint(uint64(sc.ParentID()), 16))
}
textMapWriter.Set("x-b3-spanid", strconv.FormatUint(uint64(sc.SpanID()), 16))
if sc.IsSampled() {
textMapWriter.Set("x-b3-sampled", "1")
} else {
textMapWriter.Set("x-b3-sampled", "0")
}
return nil
}
// Extract conforms to the Extractor interface for encoding Zipkin HTTP B3 headers
func (p Propagator) Extract(abstractCarrier interface{}) (jaeger.SpanContext, error) {
textMapReader, ok := abstractCarrier.(opentracing.TextMapReader)
if !ok {
return jaeger.SpanContext{}, opentracing.ErrInvalidCarrier
}
var traceID uint64
var spanID uint64
var parentID uint64
sampled := false
err := textMapReader.ForeachKey(func(rawKey, value string) error {
key := strings.ToLower(rawKey) // TODO not necessary for plain TextMap
var err error
if key == "x-b3-traceid" {
traceID, err = strconv.ParseUint(value, 16, 64)
} else if key == "x-b3-parentspanid" {
parentID, err = strconv.ParseUint(value, 16, 64)
} else if key == "x-b3-spanid" {
spanID, err = strconv.ParseUint(value, 16, 64)
} else if key == "x-b3-sampled" && value == "1" {
sampled = true
}
return err
})
if err != nil {
return jaeger.SpanContext{}, err
}
if traceID == 0 {
return jaeger.SpanContext{}, opentracing.ErrSpanContextNotFound
}
return jaeger.NewSpanContext(
jaeger.TraceID{Low: traceID},
jaeger.SpanID(spanID),
jaeger.SpanID(parentID),
sampled, nil), nil
}

View file

@ -1,22 +1,16 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2017 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Licensed under the Apache License, Version 2.0 (the "License");
// of this software and associated documentation files (the "Software"), to deal // you may not use this file except in compliance with the License.
// in the Software without restriction, including without limitation the rights // You may obtain a copy of the License at
// 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:
// //
// The above copyright notice and this permission notice shall be included in // http://www.apache.org/licenses/LICENSE-2.0
// all copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // Unless required by applicable law or agreed to in writing, software
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // distributed under the License is distributed on an "AS IS" BASIS,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // See the License for the specific language governing permissions and
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // limitations under the License.
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package jaeger package jaeger

View file

@ -286,6 +286,11 @@ func (l *LocalFactory) newNamespace(name string) string {
if l.namespace == "" { if l.namespace == "" {
return name return name
} }
if name == "" {
return l.namespace
}
return l.namespace + "." + name return l.namespace + "." + name
} }