remove unused code from vendor
This commit is contained in:
@@ -1 +0,0 @@
|
||||
/crossdock
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
FROM scratch
|
||||
|
||||
ADD crossdock /
|
||||
|
||||
ENV AGENT_HOST_PORT=jaeger-agent:5775
|
||||
ENV SAMPLING_SERVER_URL=http://test_driver:5778/sampling
|
||||
|
||||
EXPOSE 8080-8082
|
||||
|
||||
CMD ["/crossdock"]
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
# Crossdock-based Integration Test Suite
|
||||
|
||||
This package implements integration test suite for testing
|
||||
interoperability between different Jaeger client libraries.
|
||||
|
||||
## Actors
|
||||
|
||||
There are five actors participating in any given test case,
|
||||
the crossdock driver itself, a Client, and three Servers, S1-S3.
|
||||
|
||||
### Driver
|
||||
|
||||
The crossdock driver reads axis and test definitions from the YAML file,
|
||||
generates permutations based on values listed for each axis, and
|
||||
makes an HTTP request to the Client, passing it the selected value
|
||||
for each axis.
|
||||
|
||||
### Client
|
||||
|
||||
Client runs as part of the `jaeger-client/go` image and orchestrates
|
||||
the actual test case with the servers S1-S3. The incoming request
|
||||
from the driver is expected to have parameters defined in
|
||||
[client/constants.go](client/constants.go), which specify
|
||||
|
||||
1. The type of test to execute (only `trace` is currently supported)
|
||||
1. Whether the trace should be sampled or not
|
||||
1. For each of the servers S1-S3:
|
||||
* the name of the server (same as docker image name, same as host name)
|
||||
* the transport to send request to that server (http or TChannel)
|
||||
* the type of client to use (e.g. in Python, `urllib2` vs. `requests`)
|
||||
|
||||
The Client translates the parameters into a "call tree" instruction set,
|
||||
and calls S1, which in turn calls S2 with the sub-set of instructions,
|
||||
and so on. Upon receiving the response from S1, the Client validates the
|
||||
response against the conditions of the test, and returns a summary result
|
||||
to the crossdock driver, indicating a success of a failure of the test.
|
||||
For the `trace` test type, the success conditions are that at all levels
|
||||
the observed tracing spans have the same trace ID, the same sampling flag
|
||||
equal to the input `sampled` parameter, and the same value of a baggage
|
||||
item. The baggage item value is randomly selected by the client at the
|
||||
start of each test.
|
||||
|
||||
### Servers
|
||||
|
||||
Servers represent examples of business services with Jaeger tracing enabled.
|
||||
Servers must be implemented for each supported language, and potentially
|
||||
multiple times for a given language depending on the framework used to build
|
||||
the service, such as Flask vs. Tornado in Python. Each implementation of the
|
||||
server may act as any of the S1-S3 servers in the test. Each server must
|
||||
implement the `TracedService` interface from
|
||||
[thrift/tracetest.thrift](thrift/tracetest.thrift):
|
||||
|
||||
service TracedService {
|
||||
TraceResponse startTrace(1: StartTraceRequest request)
|
||||
TraceResponse joinTrace(1: JoinTraceRequest request)
|
||||
}
|
||||
|
||||
* In `startTrace` the server is supposed to ignore any trace it may have
|
||||
received via inbound request and start a brand new trace, with the
|
||||
sampling flag set appropriately, using `sampling.priority` tag,
|
||||
see [Go server implementation](server/trace.go) for example.
|
||||
* In `joinTrace` the server is supposed to respect the trace in the
|
||||
inbound request and propagate it to the outbound downstream request.
|
||||
|
||||
The response from the server contains the information about the current
|
||||
tracing span it has observed (or started), including trace ID, sampling
|
||||
flag, and the value of a baggage item. For S1 and S2 the response also
|
||||
includes the response of the downstream server.
|
||||
|
||||
## Running the tests
|
||||
|
||||
The intended setup is that every commit to master branch of each of the client
|
||||
libraries results in a build of a new docker image (or images, e.g. in Python).
|
||||
When a new pull request is tested against one of the libraries, it will build
|
||||
a new image from the modified version of the library, and use the existing
|
||||
images for the other languages. The `docker-compose.yaml` file refers to those
|
||||
images by name.
|
||||
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
// 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 client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/crossdock/crossdock-go"
|
||||
|
||||
"github.com/uber/jaeger-client-go/crossdock/common"
|
||||
)
|
||||
|
||||
// Client is a controller for the tests
|
||||
type Client struct {
|
||||
ClientHostPort string
|
||||
ServerPortHTTP string
|
||||
ServerPortTChannel string
|
||||
listener net.Listener
|
||||
hostMapper func(service string) string
|
||||
}
|
||||
|
||||
// Start begins a blocking Crossdock client
|
||||
func (c *Client) Start() error {
|
||||
if err := c.Listen(); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Serve()
|
||||
}
|
||||
|
||||
// AsyncStart begins a Crossdock client in the background,
|
||||
// but does not return until it started serving.
|
||||
func (c *Client) AsyncStart() error {
|
||||
if err := c.Listen(); err != nil {
|
||||
return err
|
||||
}
|
||||
var started sync.WaitGroup
|
||||
started.Add(1)
|
||||
go func() {
|
||||
started.Done()
|
||||
c.Serve()
|
||||
}()
|
||||
started.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Listen initializes the server
|
||||
func (c *Client) Listen() error {
|
||||
c.setDefaultPort(&c.ClientHostPort, ":"+common.DefaultClientPortHTTP)
|
||||
c.setDefaultPort(&c.ServerPortHTTP, common.DefaultServerPortHTTP)
|
||||
c.setDefaultPort(&c.ServerPortTChannel, common.DefaultServerPortTChannel)
|
||||
|
||||
behaviors := crossdock.Behaviors{
|
||||
behaviorTrace: c.trace,
|
||||
}
|
||||
|
||||
http.Handle("/", crossdock.Handler(behaviors, true))
|
||||
|
||||
listener, err := net.Listen("tcp", c.ClientHostPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.listener = listener
|
||||
c.ClientHostPort = listener.Addr().String()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Serve starts service crossdock traffic. This is a blocking call.
|
||||
func (c *Client) Serve() error {
|
||||
return http.Serve(c.listener, nil)
|
||||
}
|
||||
|
||||
// Close stops the client
|
||||
func (c *Client) Close() error {
|
||||
return c.listener.Close()
|
||||
}
|
||||
|
||||
// URL returns a URL that the client can be accessed on
|
||||
func (c *Client) URL() string {
|
||||
return fmt.Sprintf("http://%s/", c.ClientHostPort)
|
||||
}
|
||||
|
||||
func (c *Client) setDefaultPort(port *string, defaultPort string) {
|
||||
if *port == "" {
|
||||
*port = defaultPort
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) mapServiceToHost(service string) string {
|
||||
mapper := c.hostMapper
|
||||
if mapper == nil {
|
||||
return service
|
||||
}
|
||||
return mapper(service)
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
// 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 client
|
||||
|
||||
// Different parameter keys and values used by the system
|
||||
const (
|
||||
// S1 instructions
|
||||
sampledParam = "sampled"
|
||||
server1NameParam = "s1name"
|
||||
// S1->S2 instructions
|
||||
server2NameParam = "s2name"
|
||||
server2TransportParam = "s2transport"
|
||||
// S2->S3 instructions
|
||||
server3NameParam = "s3name"
|
||||
server3TransportParam = "s3transport"
|
||||
|
||||
transportHTTP = "http"
|
||||
transportTChannel = "tchannel"
|
||||
transportDummy = "dummy"
|
||||
|
||||
behaviorTrace = "trace"
|
||||
|
||||
// RoleS1 is the name of the role for server S1
|
||||
RoleS1 = "S1"
|
||||
|
||||
// RoleS2 is the name of the role for server S2
|
||||
RoleS2 = "S2"
|
||||
|
||||
// RoleS3 is the name of the role for server S3
|
||||
RoleS3 = "S3"
|
||||
)
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
// 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 client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/crossdock/crossdock-go"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/uber/jaeger-client-go/crossdock/common"
|
||||
"github.com/uber/jaeger-client-go/crossdock/log"
|
||||
"github.com/uber/jaeger-client-go/crossdock/thrift/tracetest"
|
||||
"github.com/uber/jaeger-client-go/utils"
|
||||
)
|
||||
|
||||
func (c *Client) trace(t crossdock.T) {
|
||||
sampled := str2bool(t.Param(sampledParam))
|
||||
baggage := randomBaggage()
|
||||
|
||||
level1 := tracetest.NewStartTraceRequest()
|
||||
level1.ServerRole = RoleS1
|
||||
level1.Sampled = sampled
|
||||
level1.Baggage = baggage
|
||||
server1 := t.Param(server1NameParam)
|
||||
|
||||
level2 := tracetest.NewDownstream()
|
||||
level2.ServiceName = t.Param(server2NameParam)
|
||||
level2.ServerRole = RoleS2
|
||||
level2.Host = c.mapServiceToHost(level2.ServiceName)
|
||||
level2.Port = c.transport2port(t.Param(server2TransportParam))
|
||||
level2.Transport = transport2transport(t.Param(server2TransportParam))
|
||||
level1.Downstream = level2
|
||||
|
||||
level3 := tracetest.NewDownstream()
|
||||
level3.ServiceName = t.Param(server3NameParam)
|
||||
level3.ServerRole = RoleS3
|
||||
level3.Host = c.mapServiceToHost(level3.ServiceName)
|
||||
level3.Port = c.transport2port(t.Param(server3TransportParam))
|
||||
level3.Transport = transport2transport(t.Param(server3TransportParam))
|
||||
level2.Downstream = level3
|
||||
|
||||
server1host := c.mapServiceToHost(server1)
|
||||
url := fmt.Sprintf("http://%s:%s/start_trace", server1host, c.ServerPortHTTP)
|
||||
resp, err := common.PostJSON(context.Background(), url, level1)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
for r := resp; r != nil; r = r.Downstream {
|
||||
if r.NotImplementedError != "" {
|
||||
t.Skipf(r.NotImplementedError)
|
||||
log.Printf("SKIP: %s", r.NotImplementedError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
traceID := resp.Span.TraceId
|
||||
if traceID == "" {
|
||||
t.Errorf("Trace ID is empty in S1(%s)", server1)
|
||||
return
|
||||
}
|
||||
|
||||
success := validateTrace(t, level1.Downstream, resp, server1, 1, traceID, sampled, baggage)
|
||||
if success {
|
||||
t.Successf("trace checks out")
|
||||
log.Printf("PASS")
|
||||
}
|
||||
}
|
||||
|
||||
func validateTrace(
|
||||
t crossdock.T,
|
||||
target *tracetest.Downstream,
|
||||
resp *tracetest.TraceResponse,
|
||||
service string,
|
||||
level int,
|
||||
traceID string,
|
||||
sampled bool,
|
||||
baggage string) bool {
|
||||
|
||||
success := true
|
||||
if traceID != resp.Span.TraceId {
|
||||
t.Errorf("Trace ID mismatch in S%d(%s): expected %s, received %s",
|
||||
level, service, traceID, resp.Span.TraceId)
|
||||
success = false
|
||||
}
|
||||
if baggage != resp.Span.Baggage {
|
||||
t.Errorf("Baggage mismatch in S%d(%s): expected %s, received %s",
|
||||
level, service, baggage, resp.Span.Baggage)
|
||||
success = false
|
||||
}
|
||||
if sampled != resp.Span.Sampled {
|
||||
t.Errorf("Sampled mismatch in S%d(%s): expected %t, received %t",
|
||||
level, service, sampled, resp.Span.Sampled)
|
||||
success = false
|
||||
}
|
||||
if target != nil {
|
||||
if resp.Downstream == nil {
|
||||
t.Errorf("Missing downstream in S%d(%s)", level, service)
|
||||
success = false
|
||||
} else {
|
||||
success = validateTrace(t, target.Downstream, resp.Downstream,
|
||||
target.Host, level+1, traceID, sampled, baggage) && success
|
||||
}
|
||||
} else if resp.Downstream != nil {
|
||||
t.Errorf("Unexpected downstream in S%d(%s)", level, service)
|
||||
success = false
|
||||
}
|
||||
return success
|
||||
}
|
||||
|
||||
func randomBaggage() string {
|
||||
r := utils.NewRand(time.Now().UnixNano())
|
||||
n := uint64(r.Int63())
|
||||
return fmt.Sprintf("%x", n)
|
||||
}
|
||||
|
||||
func str2bool(v string) bool {
|
||||
switch v {
|
||||
case "true":
|
||||
return true
|
||||
case "false":
|
||||
return false
|
||||
default:
|
||||
panic(v + " is not a Boolean")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) transport2port(v string) string {
|
||||
switch v {
|
||||
case transportHTTP:
|
||||
return c.ServerPortHTTP
|
||||
case transportTChannel:
|
||||
return c.ServerPortTChannel
|
||||
case transportDummy:
|
||||
return "9999"
|
||||
default:
|
||||
panic("Unknown protocol " + v)
|
||||
}
|
||||
}
|
||||
|
||||
func transport2transport(v string) tracetest.Transport {
|
||||
switch v {
|
||||
case transportHTTP:
|
||||
return tracetest.Transport_HTTP
|
||||
case transportTChannel:
|
||||
return tracetest.Transport_TCHANNEL
|
||||
case transportDummy:
|
||||
return tracetest.Transport_DUMMY
|
||||
default:
|
||||
panic("Unknown protocol " + v)
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
// 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 common
|
||||
|
||||
const (
|
||||
// DefaultClientPortHTTP is the port where the client (controller) runs
|
||||
DefaultClientPortHTTP = "8080"
|
||||
|
||||
// DefaultServerPortHTTP is the port where HTTP server runs
|
||||
DefaultServerPortHTTP = "8081"
|
||||
|
||||
// DefaultServerPortTChannel is the port where TChannel server runs
|
||||
DefaultServerPortTChannel = "8082"
|
||||
|
||||
// DefaultServiceName is the service name used by TChannel server
|
||||
DefaultServiceName = "go"
|
||||
|
||||
// DefaultTracerServiceName is the service name used by the tracer
|
||||
DefaultTracerServiceName = "crossdock-go"
|
||||
)
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
// 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 common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/uber/jaeger-client-go/crossdock/thrift/tracetest"
|
||||
"github.com/uber/jaeger-client-go/utils"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// PostJSON sends a POST request to `url` with body containing JSON-serialized `req`.
|
||||
// It injects tracing span into the headers (if found in the context).
|
||||
// It returns parsed TraceResponse, or error.
|
||||
func PostJSON(ctx context.Context, url string, req interface{}) (*tracetest.TraceResponse, error) {
|
||||
data, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
|
||||
span, err := injectSpan(ctx, httpReq)
|
||||
if span != nil {
|
||||
defer span.Finish()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result tracetest.TraceResponse
|
||||
err = utils.ReadJSON(resp, &result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func injectSpan(ctx context.Context, req *http.Request) (opentracing.Span, error) {
|
||||
span := opentracing.SpanFromContext(ctx)
|
||||
if span == nil {
|
||||
return nil, nil
|
||||
}
|
||||
span = span.Tracer().StartSpan("post", opentracing.ChildOf(span.Context()))
|
||||
ext.SpanKindRPCClient.Set(span)
|
||||
c := opentracing.HTTPHeadersCarrier(req.Header)
|
||||
err := span.Tracer().Inject(span.Context(), opentracing.HTTPHeaders, c)
|
||||
return span, err
|
||||
}
|
||||
-145
@@ -1,145 +0,0 @@
|
||||
// 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 endtoend
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
|
||||
"github.com/uber/jaeger-client-go"
|
||||
"github.com/uber/jaeger-client-go/config"
|
||||
"github.com/uber/jaeger-client-go/crossdock/common"
|
||||
"github.com/uber/jaeger-client-go/crossdock/log"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultSamplerType = jaeger.SamplerTypeRemote
|
||||
|
||||
endToEndConfig = config.Configuration{
|
||||
Disabled: false,
|
||||
Sampler: &config.SamplerConfig{
|
||||
Type: defaultSamplerType,
|
||||
Param: 1.0,
|
||||
SamplingRefreshInterval: 5 * time.Second,
|
||||
},
|
||||
Reporter: &config.ReporterConfig{
|
||||
BufferFlushInterval: time.Second,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
/*Handler handles creating traces from a http request.
|
||||
*
|
||||
* json: {
|
||||
* "type": "remote",
|
||||
* "operation": "operationName",
|
||||
* "count": 2,
|
||||
* "tags": {
|
||||
* "key": "value"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Given the above json payload, the handler will use a tracer with the RemotelyControlledSampler
|
||||
* to create 2 traces for "operationName" operation with the tags: {"key":"value"}. These traces
|
||||
* are reported to the agent with the hostname "test_driver".
|
||||
*/
|
||||
type Handler struct {
|
||||
sync.RWMutex
|
||||
|
||||
tracers map[string]opentracing.Tracer
|
||||
agentHostPort string
|
||||
samplingServerURL string
|
||||
}
|
||||
|
||||
type traceRequest struct {
|
||||
Type string `json:"type"`
|
||||
Operation string `json:"operation"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// NewHandler returns a Handler.
|
||||
func NewHandler(agentHostPort string, samplingServerURL string) *Handler {
|
||||
return &Handler{
|
||||
agentHostPort: agentHostPort,
|
||||
samplingServerURL: samplingServerURL,
|
||||
tracers: make(map[string]opentracing.Tracer),
|
||||
}
|
||||
}
|
||||
|
||||
// init initializes the handler with a tracer
|
||||
func (h *Handler) init(cfg config.Configuration) error {
|
||||
if cfg.Sampler != nil && cfg.Sampler.SamplingServerURL == "" {
|
||||
cfg.Sampler.SamplingServerURL = h.samplingServerURL
|
||||
}
|
||||
if cfg.Reporter != nil && cfg.Reporter.LocalAgentHostPort == "" {
|
||||
cfg.Reporter.LocalAgentHostPort = h.agentHostPort
|
||||
}
|
||||
tracer, _, err := cfg.New(common.DefaultTracerServiceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.tracers[cfg.Sampler.Type] = tracer
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) getTracer(samplerType string) opentracing.Tracer {
|
||||
if samplerType == "" {
|
||||
samplerType = defaultSamplerType
|
||||
}
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
tracer, ok := h.tracers[samplerType]
|
||||
if !ok {
|
||||
endToEndConfig.Sampler.Type = samplerType
|
||||
if err := h.init(endToEndConfig); err != nil {
|
||||
log.Printf("Failed to create tracer: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
tracer, _ = h.tracers[samplerType]
|
||||
}
|
||||
return tracer
|
||||
}
|
||||
|
||||
// GenerateTraces creates traces given the parameters in the request.
|
||||
func (h *Handler) GenerateTraces(w http.ResponseWriter, r *http.Request) {
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
var req traceRequest
|
||||
if err := decoder.Decode(&req); err != nil {
|
||||
http.Error(w, fmt.Sprintf("JSON payload is invalid: %s", err.Error()), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
tracer := h.getTracer(req.Type)
|
||||
if tracer == nil {
|
||||
http.Error(w, "Tracer is not initialized", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
generateTraces(tracer, &req)
|
||||
}
|
||||
|
||||
func generateTraces(tracer opentracing.Tracer, r *traceRequest) {
|
||||
for i := 0; i < r.Count; i++ {
|
||||
span := tracer.StartSpan(r.Operation)
|
||||
for k, v := range r.Tags {
|
||||
span.SetTag(k, v)
|
||||
}
|
||||
span.Finish()
|
||||
}
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
// 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 log
|
||||
|
||||
import (
|
||||
real_log "log"
|
||||
)
|
||||
|
||||
// Enabled controls logging from crossdock tests. It is enabled in main.go, but off in unit tests.
|
||||
var Enabled bool
|
||||
|
||||
// Printf delegates to log.Printf if Enabled == true
|
||||
func Printf(msg string, args ...interface{}) {
|
||||
if Enabled {
|
||||
real_log.Printf(msg, args)
|
||||
}
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
|
||||
"github.com/uber/jaeger-client-go"
|
||||
"github.com/uber/jaeger-client-go/crossdock/client"
|
||||
"github.com/uber/jaeger-client-go/crossdock/common"
|
||||
"github.com/uber/jaeger-client-go/crossdock/log"
|
||||
"github.com/uber/jaeger-client-go/crossdock/server"
|
||||
jlog "github.com/uber/jaeger-client-go/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Enabled = true
|
||||
|
||||
agentHostPort, ok := os.LookupEnv("AGENT_HOST_PORT")
|
||||
if !ok {
|
||||
jlog.StdLogger.Error("env AGENT_HOST_PORT is not specified!")
|
||||
}
|
||||
sServerURL, ok := os.LookupEnv("SAMPLING_SERVER_URL")
|
||||
if !ok {
|
||||
jlog.StdLogger.Error("env SAMPLING_SERVER_URL is not specified!")
|
||||
}
|
||||
|
||||
tracer, tCloser := initTracer()
|
||||
defer tCloser.Close()
|
||||
|
||||
s := &server.Server{Tracer: tracer, SamplingServerURL: sServerURL, AgentHostPort: agentHostPort}
|
||||
if err := s.Start(); err != nil {
|
||||
panic(err.Error())
|
||||
} else {
|
||||
defer s.Close()
|
||||
}
|
||||
client := &client.Client{}
|
||||
if err := client.Start(); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func initTracer() (opentracing.Tracer, io.Closer) {
|
||||
t, c := jaeger.NewTracer(
|
||||
common.DefaultTracerServiceName,
|
||||
jaeger.NewConstSampler(false),
|
||||
jaeger.NewLoggingReporter(jlog.StdLogger))
|
||||
return t, c
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
XDOCK_YAML=crossdock/docker-compose.yml
|
||||
|
||||
JAEGER_COMPOSE_URL=https://raw.githubusercontent.com/jaegertracing/jaeger/master/docker-compose/jaeger-docker-compose.yml
|
||||
XDOCK_JAEGER_YAML=crossdock/jaeger-docker-compose.yml
|
||||
|
||||
.PHONY: crossdock-linux-bin
|
||||
crossdock-linux-bin:
|
||||
CGO_ENABLED=0 GOOS=linux time go build -a -installsuffix cgo -o crossdock/crossdock ./crossdock
|
||||
|
||||
.PHONY: crossdock
|
||||
crossdock: crossdock-linux-bin crossdock-download-jaeger
|
||||
docker-compose -f $(XDOCK_YAML) -f $(XDOCK_JAEGER_YAML) kill go
|
||||
docker-compose -f $(XDOCK_YAML) -f $(XDOCK_JAEGER_YAML) rm -f go
|
||||
docker-compose -f $(XDOCK_YAML) -f $(XDOCK_JAEGER_YAML) build go
|
||||
docker-compose -f $(XDOCK_YAML) -f $(XDOCK_JAEGER_YAML) run crossdock 2>&1 | tee run-crossdock.log
|
||||
grep 'Tests passed!' run-crossdock.log
|
||||
|
||||
.PHONY: crossdock-fresh
|
||||
crossdock-fresh: crossdock-linux-bin crossdock-download-jaeger
|
||||
docker-compose -f $(XDOCK_JAEGER_YAML) -f $(XDOCK_YAML) kill
|
||||
docker-compose -f $(XDOCK_JAEGER_YAML) -f $(XDOCK_YAML) rm --force
|
||||
docker-compose -f $(XDOCK_JAEGER_YAML) -f $(XDOCK_YAML) pull
|
||||
docker-compose -f $(XDOCK_JAEGER_YAML) -f $(XDOCK_YAML) build
|
||||
docker-compose -f $(XDOCK_JAEGER_YAML) -f $(XDOCK_YAML) run crossdock
|
||||
|
||||
.PHONE: crossdock-logs
|
||||
crossdock-logs: crossdock-download-jaeger
|
||||
docker-compose -f $(XDOCK_JAEGER_YAML) -f $(XDOCK_YAML) logs
|
||||
|
||||
.PHONY: crossdock-download-jaeger
|
||||
crossdock-download-jaeger:
|
||||
curl -o $(XDOCK_JAEGER_YAML) $(JAEGER_COMPOSE_URL)
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
// 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 server
|
||||
|
||||
import "errors"
|
||||
|
||||
// BaggageKey is the key used to pass baggage item
|
||||
const BaggageKey = "crossdock-baggage-key"
|
||||
|
||||
var (
|
||||
errNoSpanObserved = errors.New("no span found in Context")
|
||||
errUnrecognizedProtocol = errors.New("unrecognized protocol for downstream call")
|
||||
errCannotStartInTChannel = errors.New("cannot start new trace in tchannel server")
|
||||
)
|
||||
-166
@@ -1,166 +0,0 @@
|
||||
// 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 server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
"github.com/uber/tchannel-go"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/uber/jaeger-client-go/crossdock/common"
|
||||
"github.com/uber/jaeger-client-go/crossdock/endtoend"
|
||||
"github.com/uber/jaeger-client-go/crossdock/log"
|
||||
"github.com/uber/jaeger-client-go/crossdock/thrift/tracetest"
|
||||
)
|
||||
|
||||
// Server implements S1-S3 servers
|
||||
type Server struct {
|
||||
HostPortHTTP string
|
||||
HostPortTChannel string
|
||||
AgentHostPort string
|
||||
SamplingServerURL string
|
||||
Tracer opentracing.Tracer
|
||||
listener net.Listener
|
||||
channel *tchannel.Channel
|
||||
eHandler *endtoend.Handler
|
||||
}
|
||||
|
||||
// Start starts the test server called by the Client and other upstream servers.
|
||||
func (s *Server) Start() error {
|
||||
if s.HostPortHTTP == "" {
|
||||
s.HostPortHTTP = ":" + common.DefaultServerPortHTTP
|
||||
}
|
||||
if s.HostPortTChannel == "" {
|
||||
s.HostPortTChannel = ":" + common.DefaultServerPortTChannel
|
||||
}
|
||||
|
||||
if err := s.startTChannelServer(s.Tracer); err != nil {
|
||||
return err
|
||||
}
|
||||
s.eHandler = endtoend.NewHandler(s.AgentHostPort, s.SamplingServerURL)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { return }) // health check
|
||||
mux.HandleFunc("/start_trace", func(w http.ResponseWriter, r *http.Request) {
|
||||
s.handleJSON(w, r, func() interface{} {
|
||||
return tracetest.NewStartTraceRequest()
|
||||
}, func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return s.doStartTrace(req.(*tracetest.StartTraceRequest))
|
||||
})
|
||||
})
|
||||
mux.HandleFunc("/join_trace", func(w http.ResponseWriter, r *http.Request) {
|
||||
s.handleJSON(w, r, func() interface{} {
|
||||
return tracetest.NewJoinTraceRequest()
|
||||
}, func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return s.doJoinTrace(ctx, req.(*tracetest.JoinTraceRequest))
|
||||
})
|
||||
})
|
||||
mux.HandleFunc("/create_traces", s.eHandler.GenerateTraces)
|
||||
|
||||
listener, err := net.Listen("tcp", s.HostPortHTTP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.listener = listener
|
||||
s.HostPortHTTP = listener.Addr().String()
|
||||
|
||||
var started sync.WaitGroup
|
||||
started.Add(1)
|
||||
go func() {
|
||||
started.Done()
|
||||
http.Serve(listener, mux)
|
||||
}()
|
||||
started.Wait()
|
||||
log.Printf("Started http server at %s\n", s.HostPortHTTP)
|
||||
return nil
|
||||
}
|
||||
|
||||
// URL returns URL of the HTTP server
|
||||
func (s *Server) URL() string {
|
||||
return fmt.Sprintf("http://%s/", s.HostPortHTTP)
|
||||
}
|
||||
|
||||
// Close stops the server
|
||||
func (s *Server) Close() error {
|
||||
return s.listener.Close()
|
||||
}
|
||||
|
||||
// GetPortHTTP returns the network port the server listens to.
|
||||
func (s *Server) GetPortHTTP() string {
|
||||
hostPort := s.HostPortHTTP
|
||||
hostPortSplit := strings.Split(hostPort, ":")
|
||||
port := hostPortSplit[len(hostPortSplit)-1]
|
||||
return port
|
||||
}
|
||||
|
||||
// GetPortTChannel returns the actual port the server listens to
|
||||
func (s *Server) GetPortTChannel() string {
|
||||
hostPortSplit := strings.Split(s.HostPortTChannel, ":")
|
||||
port := hostPortSplit[len(hostPortSplit)-1]
|
||||
return port
|
||||
}
|
||||
|
||||
func (s *Server) handleJSON(
|
||||
w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
newReq func() interface{},
|
||||
handle func(ctx context.Context, req interface{}) (interface{}, error),
|
||||
) {
|
||||
spanCtx, err := s.Tracer.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header))
|
||||
if err != nil && err != opentracing.ErrSpanContextNotFound {
|
||||
http.Error(w, fmt.Sprintf("Cannot read request body: %+v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
span := s.Tracer.StartSpan("post", ext.RPCServerOption(spanCtx))
|
||||
ctx := opentracing.ContextWithSpan(context.Background(), span)
|
||||
defer span.Finish()
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Cannot read request body: %+v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
log.Printf("Server request: %s", string(body))
|
||||
req := newReq()
|
||||
if err := json.Unmarshal(body, req); err != nil {
|
||||
http.Error(w, fmt.Sprintf("Cannot parse request JSON: %+v. body=[%s]", err, string(body)), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
resp, err := handle(ctx, req)
|
||||
if err != nil {
|
||||
log.Printf("Handle error: %s", err.Error())
|
||||
http.Error(w, fmt.Sprintf("Execution error: %+v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Cannot marshall response to JSON: %+v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
log.Printf("Server response: %s", string(json))
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
if _, err := w.Write(json); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
// 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 server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/uber/tchannel-go"
|
||||
"github.com/uber/tchannel-go/thrift"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/uber/jaeger-client-go/crossdock/log"
|
||||
"github.com/uber/jaeger-client-go/crossdock/thrift/tracetest"
|
||||
)
|
||||
|
||||
func (s *Server) startTChannelServer(tracer opentracing.Tracer) error {
|
||||
channelOpts := &tchannel.ChannelOptions{
|
||||
Tracer: tracer,
|
||||
}
|
||||
ch, err := tchannel.NewChannel("go", channelOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
server := thrift.NewServer(ch)
|
||||
|
||||
s.channel = ch
|
||||
|
||||
handler := tracetest.NewTChanTracedServiceServer(s)
|
||||
server.Register(handler)
|
||||
|
||||
if err := ch.ListenAndServe(s.HostPortTChannel); err != nil {
|
||||
return err
|
||||
}
|
||||
s.HostPortTChannel = ch.PeerInfo().HostPort
|
||||
log.Printf("Started tchannel server at %s\n", s.HostPortTChannel)
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartTrace implements StartTrace() of TChanTracedService
|
||||
func (s *Server) StartTrace(ctx thrift.Context, request *tracetest.StartTraceRequest) (*tracetest.TraceResponse, error) {
|
||||
return nil, errCannotStartInTChannel
|
||||
}
|
||||
|
||||
// JoinTrace implements JoinTrace() of TChanTracedService
|
||||
func (s *Server) JoinTrace(ctx thrift.Context, request *tracetest.JoinTraceRequest) (*tracetest.TraceResponse, error) {
|
||||
log.Printf("tchannel server handling JoinTrace")
|
||||
return s.prepareResponse(ctx, request.ServerRole, request.Downstream)
|
||||
}
|
||||
|
||||
func (s *Server) callDownstreamTChannel(ctx context.Context, target *tracetest.Downstream) (*tracetest.TraceResponse, error) {
|
||||
req := &tracetest.JoinTraceRequest{
|
||||
ServerRole: target.ServerRole,
|
||||
Downstream: target.Downstream,
|
||||
}
|
||||
|
||||
hostPort := fmt.Sprintf("%s:%s", target.Host, target.Port)
|
||||
log.Printf("calling downstream '%s' over tchannel:%s", target.ServiceName, hostPort)
|
||||
|
||||
channelOpts := &tchannel.ChannelOptions{
|
||||
Tracer: s.Tracer,
|
||||
}
|
||||
ch, err := tchannel.NewChannel("tchannel-client", channelOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := &thrift.ClientOptions{HostPort: hostPort}
|
||||
thriftClient := thrift.NewClient(ch, target.ServiceName, opts)
|
||||
|
||||
client := tracetest.NewTChanTracedServiceClient(thriftClient)
|
||||
ctx, cx := context.WithTimeout(ctx, time.Second)
|
||||
defer cx()
|
||||
return client.JoinTrace(thrift.Wrap(ctx), req)
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
// 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 server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/uber/jaeger-client-go"
|
||||
"github.com/uber/jaeger-client-go/crossdock/common"
|
||||
"github.com/uber/jaeger-client-go/crossdock/log"
|
||||
"github.com/uber/jaeger-client-go/crossdock/thrift/tracetest"
|
||||
)
|
||||
|
||||
func (s *Server) doStartTrace(req *tracetest.StartTraceRequest) (*tracetest.TraceResponse, error) {
|
||||
span := s.Tracer.StartSpan(req.ServerRole)
|
||||
if req.Sampled {
|
||||
ext.SamplingPriority.Set(span, 1)
|
||||
}
|
||||
span.SetBaggageItem(BaggageKey, req.Baggage)
|
||||
defer span.Finish()
|
||||
|
||||
ctx := opentracing.ContextWithSpan(context.Background(), span)
|
||||
|
||||
return s.prepareResponse(ctx, req.ServerRole, req.Downstream)
|
||||
}
|
||||
|
||||
func (s *Server) doJoinTrace(ctx context.Context, req *tracetest.JoinTraceRequest) (*tracetest.TraceResponse, error) {
|
||||
return s.prepareResponse(ctx, req.ServerRole, req.Downstream)
|
||||
}
|
||||
|
||||
func (s *Server) prepareResponse(ctx context.Context, role string, reqDwn *tracetest.Downstream) (*tracetest.TraceResponse, error) {
|
||||
observedSpan, err := observeSpan(ctx, s.Tracer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := tracetest.NewTraceResponse()
|
||||
resp.Span = observedSpan
|
||||
|
||||
if reqDwn != nil {
|
||||
downstreamResp, err := s.callDownstream(ctx, role, reqDwn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Downstream = downstreamResp
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *Server) callDownstream(ctx context.Context, role string, downstream *tracetest.Downstream) (*tracetest.TraceResponse, error) {
|
||||
switch downstream.Transport {
|
||||
case tracetest.Transport_HTTP:
|
||||
return s.callDownstreamHTTP(ctx, downstream)
|
||||
case tracetest.Transport_TCHANNEL:
|
||||
return s.callDownstreamTChannel(ctx, downstream)
|
||||
case tracetest.Transport_DUMMY:
|
||||
return &tracetest.TraceResponse{NotImplementedError: "DUMMY transport not implemented"}, nil
|
||||
default:
|
||||
return nil, errUnrecognizedProtocol
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) callDownstreamHTTP(ctx context.Context, target *tracetest.Downstream) (*tracetest.TraceResponse, error) {
|
||||
req := &tracetest.JoinTraceRequest{
|
||||
ServerRole: target.ServerRole,
|
||||
Downstream: target.Downstream,
|
||||
}
|
||||
url := fmt.Sprintf("http://%s:%s/join_trace", target.Host, target.Port)
|
||||
log.Printf("Calling downstream service '%s' at %s", target.ServiceName, url)
|
||||
return common.PostJSON(ctx, url, req)
|
||||
}
|
||||
|
||||
func observeSpan(ctx context.Context, tracer opentracing.Tracer) (*tracetest.ObservedSpan, error) {
|
||||
span := opentracing.SpanFromContext(ctx)
|
||||
if span == nil {
|
||||
return nil, errNoSpanObserved
|
||||
}
|
||||
sc := span.Context().(jaeger.SpanContext)
|
||||
observedSpan := tracetest.NewObservedSpan()
|
||||
observedSpan.TraceId = sc.TraceID().String()
|
||||
observedSpan.Sampled = sc.IsSampled()
|
||||
observedSpan.Baggage = span.BaggageItem(BaggageKey)
|
||||
return observedSpan, nil
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
// Autogenerated by Thrift Compiler (0.9.3)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
|
||||
package tracetest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
)
|
||||
|
||||
// (needed to ensure safety because of naive import list construction.)
|
||||
var _ = thrift.ZERO
|
||||
var _ = fmt.Printf
|
||||
var _ = bytes.Equal
|
||||
|
||||
func init() {
|
||||
}
|
||||
Generated
Vendored
-137
@@ -1,137 +0,0 @@
|
||||
// @generated Code generated by thrift-gen. Do not modify.
|
||||
|
||||
// Package tracetest is generated code used to make or handle TChannel calls using Thrift.
|
||||
package tracetest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
athrift "github.com/apache/thrift/lib/go/thrift"
|
||||
"github.com/uber/tchannel-go/thrift"
|
||||
)
|
||||
|
||||
// Interfaces for the service and client for the services defined in the IDL.
|
||||
|
||||
// TChanTracedService is the interface that defines the server handler and client interface.
|
||||
type TChanTracedService interface {
|
||||
JoinTrace(ctx thrift.Context, request *JoinTraceRequest) (*TraceResponse, error)
|
||||
StartTrace(ctx thrift.Context, request *StartTraceRequest) (*TraceResponse, error)
|
||||
}
|
||||
|
||||
// Implementation of a client and service handler.
|
||||
|
||||
type tchanTracedServiceClient struct {
|
||||
thriftService string
|
||||
client thrift.TChanClient
|
||||
}
|
||||
|
||||
func NewTChanTracedServiceInheritedClient(thriftService string, client thrift.TChanClient) *tchanTracedServiceClient {
|
||||
return &tchanTracedServiceClient{
|
||||
thriftService,
|
||||
client,
|
||||
}
|
||||
}
|
||||
|
||||
// NewTChanTracedServiceClient creates a client that can be used to make remote calls.
|
||||
func NewTChanTracedServiceClient(client thrift.TChanClient) TChanTracedService {
|
||||
return NewTChanTracedServiceInheritedClient("TracedService", client)
|
||||
}
|
||||
|
||||
func (c *tchanTracedServiceClient) JoinTrace(ctx thrift.Context, request *JoinTraceRequest) (*TraceResponse, error) {
|
||||
var resp TracedServiceJoinTraceResult
|
||||
args := TracedServiceJoinTraceArgs{
|
||||
Request: request,
|
||||
}
|
||||
success, err := c.client.Call(ctx, c.thriftService, "joinTrace", &args, &resp)
|
||||
if err == nil && !success {
|
||||
}
|
||||
|
||||
return resp.GetSuccess(), err
|
||||
}
|
||||
|
||||
func (c *tchanTracedServiceClient) StartTrace(ctx thrift.Context, request *StartTraceRequest) (*TraceResponse, error) {
|
||||
var resp TracedServiceStartTraceResult
|
||||
args := TracedServiceStartTraceArgs{
|
||||
Request: request,
|
||||
}
|
||||
success, err := c.client.Call(ctx, c.thriftService, "startTrace", &args, &resp)
|
||||
if err == nil && !success {
|
||||
}
|
||||
|
||||
return resp.GetSuccess(), err
|
||||
}
|
||||
|
||||
type tchanTracedServiceServer struct {
|
||||
handler TChanTracedService
|
||||
}
|
||||
|
||||
// NewTChanTracedServiceServer wraps a handler for TChanTracedService so it can be
|
||||
// registered with a thrift.Server.
|
||||
func NewTChanTracedServiceServer(handler TChanTracedService) thrift.TChanServer {
|
||||
return &tchanTracedServiceServer{
|
||||
handler,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *tchanTracedServiceServer) Service() string {
|
||||
return "TracedService"
|
||||
}
|
||||
|
||||
func (s *tchanTracedServiceServer) Methods() []string {
|
||||
return []string{
|
||||
"joinTrace",
|
||||
"startTrace",
|
||||
}
|
||||
}
|
||||
|
||||
func (s *tchanTracedServiceServer) Handle(ctx thrift.Context, methodName string, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
|
||||
switch methodName {
|
||||
case "joinTrace":
|
||||
return s.handleJoinTrace(ctx, protocol)
|
||||
case "startTrace":
|
||||
return s.handleStartTrace(ctx, protocol)
|
||||
|
||||
default:
|
||||
return false, nil, fmt.Errorf("method %v not found in service %v", methodName, s.Service())
|
||||
}
|
||||
}
|
||||
|
||||
func (s *tchanTracedServiceServer) handleJoinTrace(ctx thrift.Context, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
|
||||
var req TracedServiceJoinTraceArgs
|
||||
var res TracedServiceJoinTraceResult
|
||||
|
||||
if err := req.Read(protocol); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
r, err :=
|
||||
s.handler.JoinTrace(ctx, req.Request)
|
||||
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
} else {
|
||||
res.Success = r
|
||||
}
|
||||
|
||||
return err == nil, &res, nil
|
||||
}
|
||||
|
||||
func (s *tchanTracedServiceServer) handleStartTrace(ctx thrift.Context, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
|
||||
var req TracedServiceStartTraceArgs
|
||||
var res TracedServiceStartTraceResult
|
||||
|
||||
if err := req.Read(protocol); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
r, err :=
|
||||
s.handler.StartTrace(ctx, req.Request)
|
||||
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
} else {
|
||||
res.Success = r
|
||||
}
|
||||
|
||||
return err == nil, &res, nil
|
||||
}
|
||||
Generated
Vendored
-747
@@ -1,747 +0,0 @@
|
||||
// Autogenerated by Thrift Compiler (0.9.3)
|
||||
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
|
||||
|
||||
package tracetest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
)
|
||||
|
||||
// (needed to ensure safety because of naive import list construction.)
|
||||
var _ = thrift.ZERO
|
||||
var _ = fmt.Printf
|
||||
var _ = bytes.Equal
|
||||
|
||||
type TracedService interface {
|
||||
// Parameters:
|
||||
// - Request
|
||||
StartTrace(request *StartTraceRequest) (r *TraceResponse, err error)
|
||||
// Parameters:
|
||||
// - Request
|
||||
JoinTrace(request *JoinTraceRequest) (r *TraceResponse, err error)
|
||||
}
|
||||
|
||||
type TracedServiceClient struct {
|
||||
Transport thrift.TTransport
|
||||
ProtocolFactory thrift.TProtocolFactory
|
||||
InputProtocol thrift.TProtocol
|
||||
OutputProtocol thrift.TProtocol
|
||||
SeqId int32
|
||||
}
|
||||
|
||||
func NewTracedServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *TracedServiceClient {
|
||||
return &TracedServiceClient{Transport: t,
|
||||
ProtocolFactory: f,
|
||||
InputProtocol: f.GetProtocol(t),
|
||||
OutputProtocol: f.GetProtocol(t),
|
||||
SeqId: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func NewTracedServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *TracedServiceClient {
|
||||
return &TracedServiceClient{Transport: t,
|
||||
ProtocolFactory: nil,
|
||||
InputProtocol: iprot,
|
||||
OutputProtocol: oprot,
|
||||
SeqId: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Parameters:
|
||||
// - Request
|
||||
func (p *TracedServiceClient) StartTrace(request *StartTraceRequest) (r *TraceResponse, err error) {
|
||||
if err = p.sendStartTrace(request); err != nil {
|
||||
return
|
||||
}
|
||||
return p.recvStartTrace()
|
||||
}
|
||||
|
||||
func (p *TracedServiceClient) sendStartTrace(request *StartTraceRequest) (err error) {
|
||||
oprot := p.OutputProtocol
|
||||
if oprot == nil {
|
||||
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
|
||||
p.OutputProtocol = oprot
|
||||
}
|
||||
p.SeqId++
|
||||
if err = oprot.WriteMessageBegin("startTrace", thrift.CALL, p.SeqId); err != nil {
|
||||
return
|
||||
}
|
||||
args := TracedServiceStartTraceArgs{
|
||||
Request: request,
|
||||
}
|
||||
if err = args.Write(oprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = oprot.WriteMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
return oprot.Flush()
|
||||
}
|
||||
|
||||
func (p *TracedServiceClient) recvStartTrace() (value *TraceResponse, 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 != "startTrace" {
|
||||
err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "startTrace failed: wrong method name")
|
||||
return
|
||||
}
|
||||
if p.SeqId != seqId {
|
||||
err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "startTrace 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, "startTrace failed: invalid message type")
|
||||
return
|
||||
}
|
||||
result := TracedServiceStartTraceResult{}
|
||||
if err = result.Read(iprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = iprot.ReadMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
value = result.GetSuccess()
|
||||
return
|
||||
}
|
||||
|
||||
// Parameters:
|
||||
// - Request
|
||||
func (p *TracedServiceClient) JoinTrace(request *JoinTraceRequest) (r *TraceResponse, err error) {
|
||||
if err = p.sendJoinTrace(request); err != nil {
|
||||
return
|
||||
}
|
||||
return p.recvJoinTrace()
|
||||
}
|
||||
|
||||
func (p *TracedServiceClient) sendJoinTrace(request *JoinTraceRequest) (err error) {
|
||||
oprot := p.OutputProtocol
|
||||
if oprot == nil {
|
||||
oprot = p.ProtocolFactory.GetProtocol(p.Transport)
|
||||
p.OutputProtocol = oprot
|
||||
}
|
||||
p.SeqId++
|
||||
if err = oprot.WriteMessageBegin("joinTrace", thrift.CALL, p.SeqId); err != nil {
|
||||
return
|
||||
}
|
||||
args := TracedServiceJoinTraceArgs{
|
||||
Request: request,
|
||||
}
|
||||
if err = args.Write(oprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = oprot.WriteMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
return oprot.Flush()
|
||||
}
|
||||
|
||||
func (p *TracedServiceClient) recvJoinTrace() (value *TraceResponse, 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 != "joinTrace" {
|
||||
err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "joinTrace failed: wrong method name")
|
||||
return
|
||||
}
|
||||
if p.SeqId != seqId {
|
||||
err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "joinTrace failed: out of sequence response")
|
||||
return
|
||||
}
|
||||
if mTypeId == thrift.EXCEPTION {
|
||||
error2 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
|
||||
var error3 error
|
||||
error3, err = error2.Read(iprot)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = iprot.ReadMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
err = error3
|
||||
return
|
||||
}
|
||||
if mTypeId != thrift.REPLY {
|
||||
err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "joinTrace failed: invalid message type")
|
||||
return
|
||||
}
|
||||
result := TracedServiceJoinTraceResult{}
|
||||
if err = result.Read(iprot); err != nil {
|
||||
return
|
||||
}
|
||||
if err = iprot.ReadMessageEnd(); err != nil {
|
||||
return
|
||||
}
|
||||
value = result.GetSuccess()
|
||||
return
|
||||
}
|
||||
|
||||
type TracedServiceProcessor struct {
|
||||
processorMap map[string]thrift.TProcessorFunction
|
||||
handler TracedService
|
||||
}
|
||||
|
||||
func (p *TracedServiceProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
|
||||
p.processorMap[key] = processor
|
||||
}
|
||||
|
||||
func (p *TracedServiceProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
|
||||
processor, ok = p.processorMap[key]
|
||||
return processor, ok
|
||||
}
|
||||
|
||||
func (p *TracedServiceProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
|
||||
return p.processorMap
|
||||
}
|
||||
|
||||
func NewTracedServiceProcessor(handler TracedService) *TracedServiceProcessor {
|
||||
|
||||
self4 := &TracedServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
|
||||
self4.processorMap["startTrace"] = &tracedServiceProcessorStartTrace{handler: handler}
|
||||
self4.processorMap["joinTrace"] = &tracedServiceProcessorJoinTrace{handler: handler}
|
||||
return self4
|
||||
}
|
||||
|
||||
func (p *TracedServiceProcessor) 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()
|
||||
x5 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
|
||||
oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
|
||||
x5.Write(oprot)
|
||||
oprot.WriteMessageEnd()
|
||||
oprot.Flush()
|
||||
return false, x5
|
||||
|
||||
}
|
||||
|
||||
type tracedServiceProcessorStartTrace struct {
|
||||
handler TracedService
|
||||
}
|
||||
|
||||
func (p *tracedServiceProcessorStartTrace) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
|
||||
args := TracedServiceStartTraceArgs{}
|
||||
if err = args.Read(iprot); err != nil {
|
||||
iprot.ReadMessageEnd()
|
||||
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
|
||||
oprot.WriteMessageBegin("startTrace", thrift.EXCEPTION, seqId)
|
||||
x.Write(oprot)
|
||||
oprot.WriteMessageEnd()
|
||||
oprot.Flush()
|
||||
return false, err
|
||||
}
|
||||
|
||||
iprot.ReadMessageEnd()
|
||||
result := TracedServiceStartTraceResult{}
|
||||
var retval *TraceResponse
|
||||
var err2 error
|
||||
if retval, err2 = p.handler.StartTrace(args.Request); err2 != nil {
|
||||
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing startTrace: "+err2.Error())
|
||||
oprot.WriteMessageBegin("startTrace", thrift.EXCEPTION, seqId)
|
||||
x.Write(oprot)
|
||||
oprot.WriteMessageEnd()
|
||||
oprot.Flush()
|
||||
return true, err2
|
||||
} else {
|
||||
result.Success = retval
|
||||
}
|
||||
if err2 = oprot.WriteMessageBegin("startTrace", 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
|
||||
}
|
||||
|
||||
type tracedServiceProcessorJoinTrace struct {
|
||||
handler TracedService
|
||||
}
|
||||
|
||||
func (p *tracedServiceProcessorJoinTrace) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
|
||||
args := TracedServiceJoinTraceArgs{}
|
||||
if err = args.Read(iprot); err != nil {
|
||||
iprot.ReadMessageEnd()
|
||||
x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
|
||||
oprot.WriteMessageBegin("joinTrace", thrift.EXCEPTION, seqId)
|
||||
x.Write(oprot)
|
||||
oprot.WriteMessageEnd()
|
||||
oprot.Flush()
|
||||
return false, err
|
||||
}
|
||||
|
||||
iprot.ReadMessageEnd()
|
||||
result := TracedServiceJoinTraceResult{}
|
||||
var retval *TraceResponse
|
||||
var err2 error
|
||||
if retval, err2 = p.handler.JoinTrace(args.Request); err2 != nil {
|
||||
x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing joinTrace: "+err2.Error())
|
||||
oprot.WriteMessageBegin("joinTrace", thrift.EXCEPTION, seqId)
|
||||
x.Write(oprot)
|
||||
oprot.WriteMessageEnd()
|
||||
oprot.Flush()
|
||||
return true, err2
|
||||
} else {
|
||||
result.Success = retval
|
||||
}
|
||||
if err2 = oprot.WriteMessageBegin("joinTrace", 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:
|
||||
// - Request
|
||||
type TracedServiceStartTraceArgs struct {
|
||||
Request *StartTraceRequest `thrift:"request,1" json:"request"`
|
||||
}
|
||||
|
||||
func NewTracedServiceStartTraceArgs() *TracedServiceStartTraceArgs {
|
||||
return &TracedServiceStartTraceArgs{}
|
||||
}
|
||||
|
||||
var TracedServiceStartTraceArgs_Request_DEFAULT *StartTraceRequest
|
||||
|
||||
func (p *TracedServiceStartTraceArgs) GetRequest() *StartTraceRequest {
|
||||
if !p.IsSetRequest() {
|
||||
return TracedServiceStartTraceArgs_Request_DEFAULT
|
||||
}
|
||||
return p.Request
|
||||
}
|
||||
func (p *TracedServiceStartTraceArgs) IsSetRequest() bool {
|
||||
return p.Request != nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceStartTraceArgs) 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 *TracedServiceStartTraceArgs) readField1(iprot thrift.TProtocol) error {
|
||||
p.Request = &StartTraceRequest{}
|
||||
if err := p.Request.Read(iprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Request), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceStartTraceArgs) Write(oprot thrift.TProtocol) error {
|
||||
if err := oprot.WriteStructBegin("startTrace_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 *TracedServiceStartTraceArgs) writeField1(oprot thrift.TProtocol) (err error) {
|
||||
if err := oprot.WriteFieldBegin("request", thrift.STRUCT, 1); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:request: ", p), err)
|
||||
}
|
||||
if err := p.Request.Write(oprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Request), err)
|
||||
}
|
||||
if err := oprot.WriteFieldEnd(); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:request: ", p), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *TracedServiceStartTraceArgs) String() string {
|
||||
if p == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("TracedServiceStartTraceArgs(%+v)", *p)
|
||||
}
|
||||
|
||||
// Attributes:
|
||||
// - Success
|
||||
type TracedServiceStartTraceResult struct {
|
||||
Success *TraceResponse `thrift:"success,0" json:"success,omitempty"`
|
||||
}
|
||||
|
||||
func NewTracedServiceStartTraceResult() *TracedServiceStartTraceResult {
|
||||
return &TracedServiceStartTraceResult{}
|
||||
}
|
||||
|
||||
var TracedServiceStartTraceResult_Success_DEFAULT *TraceResponse
|
||||
|
||||
func (p *TracedServiceStartTraceResult) GetSuccess() *TraceResponse {
|
||||
if !p.IsSetSuccess() {
|
||||
return TracedServiceStartTraceResult_Success_DEFAULT
|
||||
}
|
||||
return p.Success
|
||||
}
|
||||
func (p *TracedServiceStartTraceResult) IsSetSuccess() bool {
|
||||
return p.Success != nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceStartTraceResult) 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 *TracedServiceStartTraceResult) readField0(iprot thrift.TProtocol) error {
|
||||
p.Success = &TraceResponse{}
|
||||
if err := p.Success.Read(iprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceStartTraceResult) Write(oprot thrift.TProtocol) error {
|
||||
if err := oprot.WriteStructBegin("startTrace_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 *TracedServiceStartTraceResult) writeField0(oprot thrift.TProtocol) (err error) {
|
||||
if p.IsSetSuccess() {
|
||||
if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
|
||||
}
|
||||
if err := p.Success.Write(oprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), 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 *TracedServiceStartTraceResult) String() string {
|
||||
if p == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("TracedServiceStartTraceResult(%+v)", *p)
|
||||
}
|
||||
|
||||
// Attributes:
|
||||
// - Request
|
||||
type TracedServiceJoinTraceArgs struct {
|
||||
Request *JoinTraceRequest `thrift:"request,1" json:"request"`
|
||||
}
|
||||
|
||||
func NewTracedServiceJoinTraceArgs() *TracedServiceJoinTraceArgs {
|
||||
return &TracedServiceJoinTraceArgs{}
|
||||
}
|
||||
|
||||
var TracedServiceJoinTraceArgs_Request_DEFAULT *JoinTraceRequest
|
||||
|
||||
func (p *TracedServiceJoinTraceArgs) GetRequest() *JoinTraceRequest {
|
||||
if !p.IsSetRequest() {
|
||||
return TracedServiceJoinTraceArgs_Request_DEFAULT
|
||||
}
|
||||
return p.Request
|
||||
}
|
||||
func (p *TracedServiceJoinTraceArgs) IsSetRequest() bool {
|
||||
return p.Request != nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceJoinTraceArgs) 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 *TracedServiceJoinTraceArgs) readField1(iprot thrift.TProtocol) error {
|
||||
p.Request = &JoinTraceRequest{}
|
||||
if err := p.Request.Read(iprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Request), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceJoinTraceArgs) Write(oprot thrift.TProtocol) error {
|
||||
if err := oprot.WriteStructBegin("joinTrace_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 *TracedServiceJoinTraceArgs) writeField1(oprot thrift.TProtocol) (err error) {
|
||||
if err := oprot.WriteFieldBegin("request", thrift.STRUCT, 1); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:request: ", p), err)
|
||||
}
|
||||
if err := p.Request.Write(oprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Request), err)
|
||||
}
|
||||
if err := oprot.WriteFieldEnd(); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field end error 1:request: ", p), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *TracedServiceJoinTraceArgs) String() string {
|
||||
if p == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("TracedServiceJoinTraceArgs(%+v)", *p)
|
||||
}
|
||||
|
||||
// Attributes:
|
||||
// - Success
|
||||
type TracedServiceJoinTraceResult struct {
|
||||
Success *TraceResponse `thrift:"success,0" json:"success,omitempty"`
|
||||
}
|
||||
|
||||
func NewTracedServiceJoinTraceResult() *TracedServiceJoinTraceResult {
|
||||
return &TracedServiceJoinTraceResult{}
|
||||
}
|
||||
|
||||
var TracedServiceJoinTraceResult_Success_DEFAULT *TraceResponse
|
||||
|
||||
func (p *TracedServiceJoinTraceResult) GetSuccess() *TraceResponse {
|
||||
if !p.IsSetSuccess() {
|
||||
return TracedServiceJoinTraceResult_Success_DEFAULT
|
||||
}
|
||||
return p.Success
|
||||
}
|
||||
func (p *TracedServiceJoinTraceResult) IsSetSuccess() bool {
|
||||
return p.Success != nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceJoinTraceResult) 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 *TracedServiceJoinTraceResult) readField0(iprot thrift.TProtocol) error {
|
||||
p.Success = &TraceResponse{}
|
||||
if err := p.Success.Read(iprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *TracedServiceJoinTraceResult) Write(oprot thrift.TProtocol) error {
|
||||
if err := oprot.WriteStructBegin("joinTrace_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 *TracedServiceJoinTraceResult) writeField0(oprot thrift.TProtocol) (err error) {
|
||||
if p.IsSetSuccess() {
|
||||
if err := oprot.WriteFieldBegin("success", thrift.STRUCT, 0); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
|
||||
}
|
||||
if err := p.Success.Write(oprot); err != nil {
|
||||
return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), 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 *TracedServiceJoinTraceResult) String() string {
|
||||
if p == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprintf("TracedServiceJoinTraceResult(%+v)", *p)
|
||||
}
|
||||
-1103
File diff suppressed because it is too large
Load Diff
-60
@@ -1,60 +0,0 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
jaeger "github.com/uber/jaeger-client-go"
|
||||
|
||||
opentracing "github.com/opentracing/opentracing-go"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
// Trace creates a field that extracts tracing information from a context and
|
||||
// includes it under the "trace" key.
|
||||
//
|
||||
// Because the opentracing APIs don't expose this information, the returned
|
||||
// zap.Field is a no-op for contexts that don't contain a span or contain a
|
||||
// non-Jaeger span.
|
||||
func Trace(ctx context.Context) zapcore.Field {
|
||||
if ctx == nil {
|
||||
return zap.Skip()
|
||||
}
|
||||
return zap.Object("trace", trace{ctx})
|
||||
}
|
||||
|
||||
type trace struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (t trace) MarshalLogObject(enc zapcore.ObjectEncoder) error {
|
||||
span := opentracing.SpanFromContext(t.ctx)
|
||||
if span == nil {
|
||||
return nil
|
||||
}
|
||||
j, ok := span.Context().(jaeger.SpanContext)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if !j.IsValid() {
|
||||
return fmt.Errorf("invalid span: %v", j.SpanID())
|
||||
}
|
||||
enc.AddString("span", j.SpanID().String())
|
||||
enc.AddString("trace", j.TraceID().String())
|
||||
return nil
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
// 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 zap
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Logger is an adapter from zap Logger to jaeger-lib Logger.
|
||||
type Logger struct {
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
// NewLogger creates a new Logger.
|
||||
func NewLogger(logger *zap.Logger) *Logger {
|
||||
return &Logger{logger: logger.Sugar()}
|
||||
}
|
||||
|
||||
// Error logs a message at error priority
|
||||
func (l *Logger) Error(msg string) {
|
||||
l.logger.Error(msg)
|
||||
}
|
||||
|
||||
// Infof logs a message at info priority
|
||||
func (l *Logger) Infof(msg string, args ...interface{}) {
|
||||
l.logger.Infof(msg, args...)
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
COVER=.cover
|
||||
ROOT_PKG=github.com/uber/jaeger-client-go/
|
||||
|
||||
if [[ -d "$COVER" ]]; then
|
||||
rm -rf "$COVER"
|
||||
fi
|
||||
mkdir -p "$COVER"
|
||||
|
||||
# If a package directory has a .nocover file, don't count it when calculating
|
||||
# coverage.
|
||||
filter=""
|
||||
for pkg in "$@"; do
|
||||
if [[ -f "$GOPATH/src/$pkg/.nocover" ]]; then
|
||||
if [[ -n "$filter" ]]; then
|
||||
filter="$filter, "
|
||||
fi
|
||||
filter="\"$pkg\": true"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
i=0
|
||||
for pkg in "$@"; do
|
||||
i=$((i + 1))
|
||||
|
||||
extracoverpkg=""
|
||||
if [[ -f "$GOPATH/src/$pkg/.extra-coverpkg" ]]; then
|
||||
extracoverpkg=$( \
|
||||
sed -e "s|^|$pkg/|g" < "$GOPATH/src/$pkg/.extra-coverpkg" \
|
||||
| tr '\n' ',')
|
||||
fi
|
||||
|
||||
coverpkg=$(go list -json "$pkg" | jq -r '
|
||||
.Deps
|
||||
| . + ["'"$pkg"'"]
|
||||
| map
|
||||
( select(startswith("'"$ROOT_PKG"'"))
|
||||
| select(contains("/vendor/") | not)
|
||||
| select(in({'"$filter"'}) | not)
|
||||
)
|
||||
| join(",")
|
||||
')
|
||||
if [[ -n "$extracoverpkg" ]]; then
|
||||
coverpkg="$extracoverpkg$coverpkg"
|
||||
fi
|
||||
|
||||
args=""
|
||||
if [[ -n "$coverpkg" ]]; then
|
||||
args="-coverprofile $COVER/cover.${i}.out" # -coverpkg $coverpkg"
|
||||
fi
|
||||
|
||||
echo go test -v -race "$pkg"
|
||||
go test $args -v -race "$pkg"
|
||||
done
|
||||
|
||||
gocovmerge "$COVER"/*.out > cover.out
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
python scripts/updateLicense.py $(git ls-files "*\.go" | grep -v thrift-gen | grep -v tracetest)
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
// 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 testutils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
|
||||
"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/sampling"
|
||||
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
|
||||
"github.com/uber/jaeger-client-go/utils"
|
||||
)
|
||||
|
||||
// StartMockAgent runs a mock representation of jaeger-agent.
|
||||
// This function returns a started server.
|
||||
func StartMockAgent() (*MockAgent, error) {
|
||||
transport, err := NewTUDPServerTransport("127.0.0.1:0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
samplingManager := newSamplingManager()
|
||||
samplingHandler := &samplingHandler{manager: samplingManager}
|
||||
samplingServer := httptest.NewServer(samplingHandler)
|
||||
|
||||
agent := &MockAgent{
|
||||
transport: transport,
|
||||
samplingMgr: samplingManager,
|
||||
samplingSrv: samplingServer,
|
||||
}
|
||||
|
||||
var started sync.WaitGroup
|
||||
started.Add(1)
|
||||
go agent.serve(&started)
|
||||
started.Wait()
|
||||
|
||||
return agent, nil
|
||||
}
|
||||
|
||||
// Close stops the serving of traffic
|
||||
func (s *MockAgent) Close() {
|
||||
atomic.StoreUint32(&s.serving, 0)
|
||||
s.transport.Close()
|
||||
s.samplingSrv.Close()
|
||||
}
|
||||
|
||||
// MockAgent is a mock representation of Jaeger Agent.
|
||||
// It receives spans over UDP, and has an HTTP endpoint for sampling strategies.
|
||||
type MockAgent struct {
|
||||
transport *TUDPTransport
|
||||
jaegerBatches []*jaeger.Batch
|
||||
mutex sync.Mutex
|
||||
serving uint32
|
||||
samplingMgr *samplingManager
|
||||
samplingSrv *httptest.Server
|
||||
}
|
||||
|
||||
// SpanServerAddr returns the UDP host:port where MockAgent listens for spans
|
||||
func (s *MockAgent) SpanServerAddr() string {
|
||||
return s.transport.Addr().String()
|
||||
}
|
||||
|
||||
// SpanServerClient returns a UDP client that can be used to send spans to the MockAgent
|
||||
func (s *MockAgent) SpanServerClient() (agent.Agent, error) {
|
||||
return utils.NewAgentClientUDP(s.SpanServerAddr(), 0)
|
||||
}
|
||||
|
||||
// SamplingServerAddr returns the host:port of HTTP server exposing sampling strategy endpoint
|
||||
func (s *MockAgent) SamplingServerAddr() string {
|
||||
return s.samplingSrv.Listener.Addr().String()
|
||||
}
|
||||
|
||||
func (s *MockAgent) serve(started *sync.WaitGroup) {
|
||||
handler := agent.NewAgentProcessor(s)
|
||||
protocolFact := thrift.NewTCompactProtocolFactory()
|
||||
buf := make([]byte, utils.UDPPacketMaxLength, utils.UDPPacketMaxLength)
|
||||
trans := thrift.NewTMemoryBufferLen(utils.UDPPacketMaxLength)
|
||||
|
||||
atomic.StoreUint32(&s.serving, 1)
|
||||
started.Done()
|
||||
for s.IsServing() {
|
||||
n, err := s.transport.Read(buf)
|
||||
if err == nil {
|
||||
trans.Write(buf[:n])
|
||||
protocol := protocolFact.GetProtocol(trans)
|
||||
handler.Process(protocol, protocol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EmitZipkinBatch is deprecated, use EmitBatch
|
||||
func (s *MockAgent) EmitZipkinBatch(spans []*zipkincore.Span) (err error) {
|
||||
// TODO remove this for 3.0.0
|
||||
return errors.New("Not implemented")
|
||||
}
|
||||
|
||||
// GetZipkinSpans is deprecated use GetJaegerBatches
|
||||
func (s *MockAgent) GetZipkinSpans() []*zipkincore.Span {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetZipkinSpans is deprecated use ResetJaegerBatches
|
||||
func (s *MockAgent) ResetZipkinSpans() {}
|
||||
|
||||
// EmitBatch implements EmitBatch() of TChanSamplingManagerServer
|
||||
func (s *MockAgent) EmitBatch(batch *jaeger.Batch) (err error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.jaegerBatches = append(s.jaegerBatches, batch)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsServing indicates whether the server is currently serving traffic
|
||||
func (s *MockAgent) IsServing() bool {
|
||||
return atomic.LoadUint32(&s.serving) == 1
|
||||
}
|
||||
|
||||
// AddSamplingStrategy registers a sampling strategy for a service
|
||||
func (s *MockAgent) AddSamplingStrategy(service string, strategy *sampling.SamplingStrategyResponse) {
|
||||
s.samplingMgr.AddSamplingStrategy(service, strategy)
|
||||
}
|
||||
|
||||
// GetJaegerBatches returns accumulated Jaeger batches
|
||||
func (s *MockAgent) GetJaegerBatches() []*jaeger.Batch {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
n := len(s.jaegerBatches)
|
||||
batches := make([]*jaeger.Batch, n, n)
|
||||
copy(batches, s.jaegerBatches)
|
||||
return batches
|
||||
}
|
||||
|
||||
// ResetJaegerBatches discards accumulated Jaeger batches
|
||||
func (s *MockAgent) ResetJaegerBatches() {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.jaegerBatches = nil
|
||||
}
|
||||
|
||||
type samplingHandler struct {
|
||||
manager *samplingManager
|
||||
}
|
||||
|
||||
func (h *samplingHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
services := r.URL.Query()["service"]
|
||||
if len(services) == 0 {
|
||||
http.Error(w, "'service' parameter is empty", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if len(services) > 1 {
|
||||
http.Error(w, "'service' parameter must occur only once", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
resp, err := h.manager.GetSamplingStrategy(services[0])
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Error retrieving strategy: %+v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
json, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
http.Error(w, "Cannot marshall Thrift to JSON", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
if _, err := w.Write(json); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
// 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 testutils
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/uber/jaeger-client-go/thrift-gen/sampling"
|
||||
)
|
||||
|
||||
func newSamplingManager() *samplingManager {
|
||||
return &samplingManager{
|
||||
sampling: make(map[string]*sampling.SamplingStrategyResponse),
|
||||
}
|
||||
}
|
||||
|
||||
type samplingManager struct {
|
||||
sampling map[string]*sampling.SamplingStrategyResponse
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// GetSamplingStrategy implements handler method of sampling.SamplingManager
|
||||
func (s *samplingManager) GetSamplingStrategy(serviceName string) (*sampling.SamplingStrategyResponse, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
if strategy, ok := s.sampling[serviceName]; ok {
|
||||
return strategy, nil
|
||||
}
|
||||
return &sampling.SamplingStrategyResponse{
|
||||
StrategyType: sampling.SamplingStrategyType_PROBABILISTIC,
|
||||
ProbabilisticSampling: &sampling.ProbabilisticSamplingStrategy{
|
||||
SamplingRate: 0.01,
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// AddSamplingStrategy registers a sampling strategy for a service
|
||||
func (s *samplingManager) AddSamplingStrategy(service string, strategy *sampling.SamplingStrategyResponse) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
s.sampling[service] = strategy
|
||||
}
|
||||
-106
@@ -1,106 +0,0 @@
|
||||
// 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 testutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
)
|
||||
|
||||
const (
|
||||
// used in RemainingBytes()
|
||||
maxRemainingBytes = ^uint64(0)
|
||||
)
|
||||
|
||||
// TUDPTransport does UDP as a thrift.TTransport (read-only, write functions not implemented).
|
||||
type TUDPTransport struct {
|
||||
conn *net.UDPConn
|
||||
addr net.Addr
|
||||
writeBuf bytes.Buffer
|
||||
closed uint32
|
||||
}
|
||||
|
||||
// NewTUDPServerTransport creates a net.UDPConn-backed TTransport for Thrift servers
|
||||
// It will listen for incoming udp packets on the specified host/port
|
||||
// Example:
|
||||
// trans, err := utils.NewTUDPClientTransport("localhost:9001")
|
||||
func NewTUDPServerTransport(hostPort string) (*TUDPTransport, error) {
|
||||
addr, err := net.ResolveUDPAddr("udp", hostPort)
|
||||
if err != nil {
|
||||
return nil, thrift.NewTTransportException(thrift.NOT_OPEN, err.Error())
|
||||
}
|
||||
conn, err := net.ListenUDP(addr.Network(), addr)
|
||||
if err != nil {
|
||||
return nil, thrift.NewTTransportException(thrift.NOT_OPEN, err.Error())
|
||||
}
|
||||
return &TUDPTransport{addr: conn.LocalAddr(), conn: conn}, nil
|
||||
}
|
||||
|
||||
// Open does nothing as connection is opened on creation
|
||||
// Required to maintain thrift.TTransport interface
|
||||
func (p *TUDPTransport) Open() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Conn retrieves the underlying net.UDPConn
|
||||
func (p *TUDPTransport) Conn() *net.UDPConn {
|
||||
return p.conn
|
||||
}
|
||||
|
||||
// IsOpen returns true if the connection is open
|
||||
func (p *TUDPTransport) IsOpen() bool {
|
||||
return p.conn != nil && atomic.LoadUint32(&p.closed) == 0
|
||||
}
|
||||
|
||||
// Close closes the connection
|
||||
func (p *TUDPTransport) Close() error {
|
||||
if p.conn != nil && atomic.CompareAndSwapUint32(&p.closed, 0, 1) {
|
||||
return p.conn.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Addr returns the address that the transport is listening on or writing to
|
||||
func (p *TUDPTransport) Addr() net.Addr {
|
||||
return p.addr
|
||||
}
|
||||
|
||||
// Read reads one UDP packet and puts it in the specified buf
|
||||
func (p *TUDPTransport) Read(buf []byte) (int, error) {
|
||||
if !p.IsOpen() {
|
||||
return 0, thrift.NewTTransportException(thrift.NOT_OPEN, "Connection not open")
|
||||
}
|
||||
n, err := p.conn.Read(buf)
|
||||
return n, thrift.NewTTransportExceptionFromError(err)
|
||||
}
|
||||
|
||||
// RemainingBytes returns the max number of bytes (same as Thrift's StreamTransport) as we
|
||||
// do not know how many bytes we have left.
|
||||
func (p *TUDPTransport) RemainingBytes() uint64 {
|
||||
return maxRemainingBytes
|
||||
}
|
||||
|
||||
// Write writes specified buf to the write buffer
|
||||
func (p *TUDPTransport) Write(buf []byte) (int, error) {
|
||||
return 0, thrift.NewTTransportException(thrift.UNKNOWN_TRANSPORT_EXCEPTION, "Write not implemented")
|
||||
}
|
||||
|
||||
// Flush flushes the write buffer as one udp packet
|
||||
func (p *TUDPTransport) Flush() error {
|
||||
return thrift.NewTTransportException(thrift.UNKNOWN_TRANSPORT_EXCEPTION, "Flush not implemented")
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
// 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 transport defines various transports that can be used with
|
||||
// RemoteReporter to send spans out of process. Transport is responsible
|
||||
// for serializing the spans into a specific format suitable for sending
|
||||
// to the tracing backend. Examples may include Thrift over UDP, Thrift
|
||||
// or JSON over HTTP, Thrift over Kafka, etc.
|
||||
//
|
||||
// Implementations are NOT required to be thread-safe; the RemoteReporter
|
||||
// is expected to only call methods on the Transport from the same go-routine.
|
||||
package transport
|
||||
-155
@@ -1,155 +0,0 @@
|
||||
// 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 transport
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
|
||||
"github.com/uber/jaeger-client-go"
|
||||
j "github.com/uber/jaeger-client-go/thrift-gen/jaeger"
|
||||
)
|
||||
|
||||
// Default timeout for http request in seconds
|
||||
const defaultHTTPTimeout = time.Second * 5
|
||||
|
||||
// HTTPTransport implements Transport by forwarding spans to a http server.
|
||||
type HTTPTransport struct {
|
||||
url string
|
||||
client *http.Client
|
||||
batchSize int
|
||||
spans []*j.Span
|
||||
process *j.Process
|
||||
httpCredentials *HTTPBasicAuthCredentials
|
||||
}
|
||||
|
||||
// HTTPBasicAuthCredentials stores credentials for HTTP basic auth.
|
||||
type HTTPBasicAuthCredentials struct {
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
// HTTPOption sets a parameter for the HttpCollector
|
||||
type HTTPOption func(c *HTTPTransport)
|
||||
|
||||
// HTTPTimeout sets maximum timeout for http request.
|
||||
func HTTPTimeout(duration time.Duration) HTTPOption {
|
||||
return func(c *HTTPTransport) { c.client.Timeout = duration }
|
||||
}
|
||||
|
||||
// HTTPBatchSize sets the maximum batch size, after which a collect will be
|
||||
// triggered. The default batch size is 100 spans.
|
||||
func HTTPBatchSize(n int) HTTPOption {
|
||||
return func(c *HTTPTransport) { c.batchSize = n }
|
||||
}
|
||||
|
||||
// HTTPBasicAuth sets the credentials required to perform HTTP basic auth
|
||||
func HTTPBasicAuth(username string, password string) HTTPOption {
|
||||
return func(c *HTTPTransport) {
|
||||
c.httpCredentials = &HTTPBasicAuthCredentials{username: username, password: password}
|
||||
}
|
||||
}
|
||||
|
||||
// NewHTTPTransport returns a new HTTP-backend transport. url should be an http
|
||||
// url of the collector to handle POST request, typically something like:
|
||||
// http://hostname:14268/api/traces?format=jaeger.thrift
|
||||
func NewHTTPTransport(url string, options ...HTTPOption) *HTTPTransport {
|
||||
c := &HTTPTransport{
|
||||
url: url,
|
||||
client: &http.Client{Timeout: defaultHTTPTimeout},
|
||||
batchSize: 100,
|
||||
spans: []*j.Span{},
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Append implements Transport.
|
||||
func (c *HTTPTransport) Append(span *jaeger.Span) (int, error) {
|
||||
if c.process == nil {
|
||||
c.process = jaeger.BuildJaegerProcessThrift(span)
|
||||
}
|
||||
jSpan := jaeger.BuildJaegerThrift(span)
|
||||
c.spans = append(c.spans, jSpan)
|
||||
if len(c.spans) >= c.batchSize {
|
||||
return c.Flush()
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Flush implements Transport.
|
||||
func (c *HTTPTransport) Flush() (int, error) {
|
||||
count := len(c.spans)
|
||||
if count == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
err := c.send(c.spans)
|
||||
c.spans = c.spans[:0]
|
||||
return count, err
|
||||
}
|
||||
|
||||
// Close implements Transport.
|
||||
func (c *HTTPTransport) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTTPTransport) send(spans []*j.Span) error {
|
||||
batch := &j.Batch{
|
||||
Spans: spans,
|
||||
Process: c.process,
|
||||
}
|
||||
body, err := serializeThrift(batch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest("POST", c.url, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-thrift")
|
||||
|
||||
if c.httpCredentials != nil {
|
||||
req.SetBasicAuth(c.httpCredentials.username, c.httpCredentials.password)
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
io.Copy(ioutil.Discard, resp.Body)
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
return fmt.Errorf("error from collector: %d", resp.StatusCode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func serializeThrift(obj thrift.TStruct) (*bytes.Buffer, error) {
|
||||
t := thrift.NewTMemoryBuffer()
|
||||
p := thrift.NewTBinaryProtocolTransport(t)
|
||||
if err := obj.Write(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t.Buffer, nil
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
// 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 provides various Transports that can be used
|
||||
// with RemoteReporter for submitting traces to Zipkin backend.
|
||||
package zipkin
|
||||
-166
@@ -1,166 +0,0 @@
|
||||
// Copyright (c) 2017 The OpenTracing Authors
|
||||
// Copyright (c) 2016 Bas van Beek
|
||||
// Copyright (c) 2016 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
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package zipkin
|
||||
|
||||
// This code is adapted from 'collector-http.go' from
|
||||
// https://github.com/openzipkin/zipkin-go-opentracing/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/apache/thrift/lib/go/thrift"
|
||||
|
||||
"github.com/uber/jaeger-client-go"
|
||||
"github.com/uber/jaeger-client-go/log"
|
||||
"github.com/uber/jaeger-client-go/thrift-gen/zipkincore"
|
||||
)
|
||||
|
||||
// Default timeout for http request in seconds
|
||||
const defaultHTTPTimeout = time.Second * 5
|
||||
|
||||
// HTTPTransport implements Transport by forwarding spans to a http server.
|
||||
type HTTPTransport struct {
|
||||
logger jaeger.Logger
|
||||
url string
|
||||
client *http.Client
|
||||
batchSize int
|
||||
batch []*zipkincore.Span
|
||||
httpCredentials *HTTPBasicAuthCredentials
|
||||
}
|
||||
|
||||
// HTTPBasicAuthCredentials stores credentials for HTTP basic auth.
|
||||
type HTTPBasicAuthCredentials struct {
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
// HTTPOption sets a parameter for the HttpCollector
|
||||
type HTTPOption func(c *HTTPTransport)
|
||||
|
||||
// HTTPLogger sets the logger used to report errors in the collection
|
||||
// process. By default, a no-op logger is used, i.e. no errors are logged
|
||||
// anywhere. It's important to set this option in a production service.
|
||||
func HTTPLogger(logger jaeger.Logger) HTTPOption {
|
||||
return func(c *HTTPTransport) { c.logger = logger }
|
||||
}
|
||||
|
||||
// HTTPTimeout sets maximum timeout for http request.
|
||||
func HTTPTimeout(duration time.Duration) HTTPOption {
|
||||
return func(c *HTTPTransport) { c.client.Timeout = duration }
|
||||
}
|
||||
|
||||
// HTTPBatchSize sets the maximum batch size, after which a collect will be
|
||||
// triggered. The default batch size is 100 spans.
|
||||
func HTTPBatchSize(n int) HTTPOption {
|
||||
return func(c *HTTPTransport) { c.batchSize = n }
|
||||
}
|
||||
|
||||
// HTTPBasicAuth sets the credentials required to perform HTTP basic auth
|
||||
func HTTPBasicAuth(username string, password string) HTTPOption {
|
||||
return func(c *HTTPTransport) {
|
||||
c.httpCredentials = &HTTPBasicAuthCredentials{username: username, password: password}
|
||||
}
|
||||
}
|
||||
|
||||
// NewHTTPTransport returns a new HTTP-backend transport. url should be an http
|
||||
// url to handle post request, typically something like:
|
||||
// http://hostname:9411/api/v1/spans
|
||||
func NewHTTPTransport(url string, options ...HTTPOption) (*HTTPTransport, error) {
|
||||
c := &HTTPTransport{
|
||||
logger: log.NullLogger,
|
||||
url: url,
|
||||
client: &http.Client{Timeout: defaultHTTPTimeout},
|
||||
batchSize: 100,
|
||||
batch: []*zipkincore.Span{},
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(c)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Append implements Transport.
|
||||
func (c *HTTPTransport) Append(span *jaeger.Span) (int, error) {
|
||||
zSpan := jaeger.BuildZipkinThrift(span)
|
||||
c.batch = append(c.batch, zSpan)
|
||||
if len(c.batch) >= c.batchSize {
|
||||
return c.Flush()
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Flush implements Transport.
|
||||
func (c *HTTPTransport) Flush() (int, error) {
|
||||
count := len(c.batch)
|
||||
if count == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
err := c.send(c.batch)
|
||||
c.batch = c.batch[:0]
|
||||
return count, err
|
||||
}
|
||||
|
||||
// Close implements Transport.
|
||||
func (c *HTTPTransport) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func httpSerialize(spans []*zipkincore.Span) (*bytes.Buffer, error) {
|
||||
t := thrift.NewTMemoryBuffer()
|
||||
p := thrift.NewTBinaryProtocolTransport(t)
|
||||
if err := p.WriteListBegin(thrift.STRUCT, len(spans)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, s := range spans {
|
||||
if err := s.Write(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := p.WriteListEnd(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t.Buffer, nil
|
||||
}
|
||||
|
||||
func (c *HTTPTransport) send(spans []*zipkincore.Span) error {
|
||||
body, err := httpSerialize(spans)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequest("POST", c.url, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-thrift")
|
||||
|
||||
if c.httpCredentials != nil {
|
||||
req.SetBasicAuth(c.httpCredentials.username, c.httpCredentials.password)
|
||||
}
|
||||
|
||||
_, err = c.client.Do(req)
|
||||
|
||||
return err
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
make crossdock
|
||||
|
||||
export REPO=jaegertracing/xdock-go
|
||||
export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
|
||||
export TAG=`if [ "$BRANCH" == "master" ]; then echo "latest"; else echo "${BRANCH///}"; fi`
|
||||
echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, REPO=$REPO, PR=$PR, BRANCH=$BRANCH, TAG=$TAG"
|
||||
|
||||
# Only push the docker container to Docker Hub for master branch
|
||||
if [[ "$BRANCH" == "master" && "$TRAVIS_SECURE_ENV_VARS" == "true" ]]; then echo 'upload to Docker Hub'; else echo 'skip docker upload for PR'; exit 0; fi
|
||||
|
||||
docker login -u $DOCKER_USER -p $DOCKER_PASS
|
||||
|
||||
set -x
|
||||
|
||||
docker build -f crossdock/Dockerfile -t $REPO:$COMMIT .
|
||||
|
||||
docker tag $REPO:$COMMIT $REPO:$TAG
|
||||
docker tag $REPO:$COMMIT $REPO:travis-$TRAVIS_BUILD_NUMBER
|
||||
docker push $REPO
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
docker version
|
||||
|
||||
# Install docker-compose
|
||||
sudo rm -f /usr/local/bin/docker-compose
|
||||
curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
|
||||
chmod +x docker-compose
|
||||
sudo mv docker-compose /usr/local/bin
|
||||
docker-compose version
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
# Zipkin compatibility features
|
||||
|
||||
## `NewZipkinB3HTTPHeaderPropagator()`
|
||||
|
||||
Adds support for injecting and extracting Zipkin B3 Propagation HTTP headers,
|
||||
for use with other Zipkin collectors.
|
||||
|
||||
```go
|
||||
|
||||
// ...
|
||||
import (
|
||||
"github.com/uber/jaeger-client-go/zipkin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// ...
|
||||
zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator()
|
||||
injector := jaeger.TracerOptions.Injector(opentracing.HTTPHeaders, zipkinPropagator)
|
||||
extractor := jaeger.TracerOptions.Extractor(opentracing.HTTPHeaders, zipkinPropagator)
|
||||
|
||||
// Zipkin shares span ID between client and server spans; it must be enabled via the following option.
|
||||
zipkinSharedRPCSpan := jaeger.TracerOptions.ZipkinSharedRPCSpan(true)
|
||||
|
||||
// create Jaeger tracer
|
||||
tracer, closer := jaeger.NewTracer(
|
||||
"myService",
|
||||
mySampler, // as usual
|
||||
myReporter // as usual
|
||||
injector,
|
||||
extractor,
|
||||
zipkinSharedRPCSpan,
|
||||
)
|
||||
}
|
||||
```
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
// 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
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user