remove unused code from vendor

This commit is contained in:
bergquist
2018-01-19 09:54:22 +01:00
parent e023f79c5a
commit 7ed643f302
6531 changed files with 6 additions and 2907556 deletions
@@ -1 +0,0 @@
/crossdock
-10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
@@ -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() {
}
@@ -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
}
@@ -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)
}
File diff suppressed because it is too large Load Diff
-60
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1,5 +0,0 @@
#!/bin/bash
set -e
python scripts/updateLicense.py $(git ls-files "*\.go" | grep -v thrift-gen | grep -v tracetest)
-189
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
-64
View File
@@ -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 xkit
import (
"fmt"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
)
// LoggerOption sets a parameter for the Logger.
type LoggerOption func(*Logger)
// MessageKey sets the key for the actual log message. By default, it's "msg".
func MessageKey(key string) LoggerOption {
return func(l *Logger) { l.messageKey = key }
}
// Logger wraps a go-kit logger instance in a Jaeger client compatible one.
type Logger struct {
infoLogger log.Logger
errorLogger log.Logger
messageKey string
}
// NewLogger creates a new Jaeger client logger from a go-kit one.
func NewLogger(kitlogger log.Logger, options ...LoggerOption) *Logger {
logger := &Logger{
infoLogger: level.Info(kitlogger),
errorLogger: level.Error(kitlogger),
messageKey: "msg",
}
for _, option := range options {
option(logger)
}
return logger
}
// Error implements the github.com/uber/jaeger-client-go/log.Logger interface.
func (l *Logger) Error(msg string) {
l.errorLogger.Log(l.messageKey, msg)
}
// Infof implements the github.com/uber/jaeger-client-go/log.Logger interface.
func (l *Logger) Infof(msg string, args ...interface{}) {
l.infoLogger.Log(l.messageKey, fmt.Sprintf(msg, args...))
}
-50
View File
@@ -1,50 +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 expvar
import (
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/expvar"
"github.com/uber/jaeger-lib/metrics/go-kit"
)
// NewFactory creates a new metrics factory using go-kit expvar package.
// buckets is the number of buckets to be used in histograms.
func NewFactory(buckets int) xkit.Factory {
return factory{
buckets: buckets,
}
}
type factory struct {
buckets int
}
func (f factory) Counter(name string) metrics.Counter {
return expvar.NewCounter(name)
}
func (f factory) Histogram(name string) metrics.Histogram {
return expvar.NewHistogram(name, f.buckets)
}
func (f factory) Gauge(name string) metrics.Gauge {
return expvar.NewGauge(name)
}
func (f factory) Capabilities() xkit.Capabilities {
return xkit.Capabilities{Tagging: false}
}
-161
View File
@@ -1,161 +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 xkit
import (
kit "github.com/go-kit/kit/metrics"
"github.com/uber/jaeger-lib/metrics"
)
// Factory provides a unified interface for creating named metrics
// from various go-kit metrics implementations.
type Factory interface {
Counter(name string) kit.Counter
Gauge(name string) kit.Gauge
Histogram(name string) kit.Histogram
Capabilities() Capabilities
}
// Capabilities describes capabilities of a specific metrics factory.
type Capabilities struct {
// Tagging indicates whether the factory has the capability for tagged metrics
Tagging bool
}
// FactoryOption is a function that adjusts some parameters of the factory.
type FactoryOption func(*factory)
// Wrap is used to create an adapter from xkit.Factory to metrics.Factory.
func Wrap(namespace string, f Factory, options ...FactoryOption) metrics.Factory {
factory := &factory{
scope: namespace,
factory: f,
scopeSep: ".",
tagsSep: ".",
tagKVSep: "_",
}
for i := range options {
options[i](factory)
}
return factory
}
// ScopeSeparator returns an option that overrides default scope separator.
func ScopeSeparator(scopeSep string) FactoryOption {
return func(f *factory) {
f.scopeSep = scopeSep
}
}
// TagsSeparator returns an option that overrides default tags separator.
func TagsSeparator(tagsSep string) FactoryOption {
return func(f *factory) {
f.tagsSep = tagsSep
}
}
type factory struct {
scope string
tags map[string]string
factory Factory
scopeSep string
tagsSep string
tagKVSep string
}
func (f *factory) subScope(name string) string {
if f.scope == "" {
return name
}
if name == "" {
return f.scope
}
return f.scope + f.scopeSep + name
}
// nameAndTagsList returns a name and tags list for the new metrics.
// The name is a concatenation of nom and the current factory scope.
// The tags list is a flattened list of passed tags merged with factory tags.
// If the underlying factory does not support tags, then the tags are
// transformed into a string and appended to the name.
func (f *factory) nameAndTagsList(nom string, tags map[string]string) (name string, tagsList []string) {
mergedTags := f.mergeTags(tags)
name = f.subScope(nom)
tagsList = f.tagsList(mergedTags)
if len(tagsList) == 0 || f.factory.Capabilities().Tagging {
return
}
name = metrics.GetKey(name, mergedTags, f.tagsSep, f.tagKVSep)
tagsList = nil
return
}
func (f *factory) Counter(name string, tags map[string]string) metrics.Counter {
name, tagsList := f.nameAndTagsList(name, tags)
counter := f.factory.Counter(name)
if len(tagsList) > 0 {
counter = counter.With(tagsList...)
}
return NewCounter(counter)
}
func (f *factory) Timer(name string, tags map[string]string) metrics.Timer {
name, tagsList := f.nameAndTagsList(name, tags)
hist := f.factory.Histogram(name)
if len(tagsList) > 0 {
hist = hist.With(tagsList...)
}
return NewTimer(hist)
}
func (f *factory) Gauge(name string, tags map[string]string) metrics.Gauge {
name, tagsList := f.nameAndTagsList(name, tags)
gauge := f.factory.Gauge(name)
if len(tagsList) > 0 {
gauge = gauge.With(tagsList...)
}
return NewGauge(gauge)
}
func (f *factory) Namespace(name string, tags map[string]string) metrics.Factory {
return &factory{
scope: f.subScope(name),
tags: f.mergeTags(tags),
factory: f.factory,
scopeSep: f.scopeSep,
tagsSep: f.tagsSep,
tagKVSep: f.tagKVSep,
}
}
func (f *factory) tagsList(a map[string]string) []string {
ret := make([]string, 0, 2*len(a))
for k, v := range a {
ret = append(ret, k, v)
}
return ret
}
func (f *factory) mergeTags(tags map[string]string) map[string]string {
ret := make(map[string]string, len(f.tags)+len(tags))
for k, v := range f.tags {
ret[k] = v
}
for k, v := range tags {
ret[k] = v
}
return ret
}
-49
View File
@@ -1,49 +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 influx
import (
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/influx"
"github.com/uber/jaeger-lib/metrics/go-kit"
)
// NewFactory creates a new metrics factory using go-kit influx package.
func NewFactory(client *influx.Influx) xkit.Factory {
return factory{
client: client,
}
}
type factory struct {
client *influx.Influx
}
func (f factory) Counter(name string) metrics.Counter {
return f.client.NewCounter(name)
}
func (f factory) Histogram(name string) metrics.Histogram {
return f.client.NewHistogram(name)
}
func (f factory) Gauge(name string) metrics.Gauge {
return f.client.NewGauge(name)
}
func (f factory) Capabilities() xkit.Capabilities {
return xkit.Capabilities{Tagging: true}
}
-66
View File
@@ -1,66 +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 xkit
import (
"time"
kit "github.com/go-kit/kit/metrics"
)
// Counter is an adapter from go-kit Counter to jaeger-lib Counter
type Counter struct {
counter kit.Counter
}
// NewCounter creates a new Counter
func NewCounter(counter kit.Counter) *Counter {
return &Counter{counter: counter}
}
// Inc adds the given value to the counter.
func (c *Counter) Inc(delta int64) {
c.counter.Add(float64(delta))
}
// Gauge is an adapter from go-kit Gauge to jaeger-lib Gauge
type Gauge struct {
gauge kit.Gauge
}
// NewGauge creates a new Gauge
func NewGauge(gauge kit.Gauge) *Gauge {
return &Gauge{gauge: gauge}
}
// Update the gauge to the value passed in.
func (g *Gauge) Update(value int64) {
g.gauge.Set(float64(value))
}
// Timer is an adapter from go-kit Histogram to jaeger-lib Timer
type Timer struct {
hist kit.Histogram
}
// NewTimer creates a new Timer
func NewTimer(hist kit.Histogram) *Timer {
return &Timer{hist: hist}
}
// Record saves the time passed in.
func (t *Timer) Record(delta time.Duration) {
t.hist.Observe(delta.Seconds())
}
-82
View File
@@ -1,82 +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 prometheus
import (
"strings"
"github.com/go-kit/kit/metrics"
kitprom "github.com/go-kit/kit/metrics/prometheus"
"github.com/prometheus/client_golang/prometheus"
"github.com/uber/jaeger-lib/metrics/go-kit"
)
var normalizer = strings.NewReplacer(
".", "_",
"-", "_",
)
// NewFactory creates a new metrics factory using go-kit prometheus package.
// buckets define the buckets into which histogram observations are counted.
// If buckets == nil, the default value prometheus.DefBuckets is used.
func NewFactory(namespace, subsystem string, buckets []float64) xkit.Factory {
return &factory{
namespace: namespace,
subsystem: subsystem,
buckets: buckets,
}
}
type factory struct {
namespace string
subsystem string
buckets []float64
}
func (f *factory) Counter(name string) metrics.Counter {
opts := prometheus.CounterOpts{
Namespace: f.namespace,
Subsystem: f.subsystem,
Name: normalizer.Replace(name),
Help: name,
}
return kitprom.NewCounterFrom(opts, nil)
}
func (f *factory) Histogram(name string) metrics.Histogram {
opts := prometheus.HistogramOpts{
Namespace: f.namespace,
Subsystem: f.subsystem,
Name: normalizer.Replace(name),
Help: name,
Buckets: f.buckets,
}
return kitprom.NewHistogramFrom(opts, nil)
}
func (f *factory) Gauge(name string) metrics.Gauge {
opts := prometheus.GaugeOpts{
Namespace: f.namespace,
Subsystem: f.subsystem,
Name: normalizer.Replace(name),
Help: name,
}
return kitprom.NewGaugeFrom(opts, nil)
}
func (f *factory) Capabilities() xkit.Capabilities {
return xkit.Capabilities{Tagging: true}
}
-107
View File
@@ -1,107 +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 multi
import (
"time"
"github.com/uber/jaeger-lib/metrics"
)
// Factory is a metrics factory that dispatches to multiple metrics backends.
type Factory struct {
factories []metrics.Factory
}
// New creates a new multi.Factory that will dispatch to multiple metrics backends.
func New(factories ...metrics.Factory) *Factory {
return &Factory{
factories: factories,
}
}
type counter struct {
counters []metrics.Counter
}
func (c *counter) Inc(delta int64) {
for _, counter := range c.counters {
counter.Inc(delta)
}
}
// Counter implements metrics.Factory interface
func (f *Factory) Counter(name string, tags map[string]string) metrics.Counter {
counter := &counter{
counters: make([]metrics.Counter, len(f.factories)),
}
for i, factory := range f.factories {
counter.counters[i] = factory.Counter(name, tags)
}
return counter
}
type timer struct {
timers []metrics.Timer
}
func (t *timer) Record(delta time.Duration) {
for _, timer := range t.timers {
timer.Record(delta)
}
}
// Timer implements metrics.Factory interface
func (f *Factory) Timer(name string, tags map[string]string) metrics.Timer {
timer := &timer{
timers: make([]metrics.Timer, len(f.factories)),
}
for i, factory := range f.factories {
timer.timers[i] = factory.Timer(name, tags)
}
return timer
}
type gauge struct {
gauges []metrics.Gauge
}
func (t *gauge) Update(value int64) {
for _, gauge := range t.gauges {
gauge.Update(value)
}
}
// Gauge implements metrics.Factory interface
func (f *Factory) Gauge(name string, tags map[string]string) metrics.Gauge {
gauge := &gauge{
gauges: make([]metrics.Gauge, len(f.factories)),
}
for i, factory := range f.factories {
gauge.gauges[i] = factory.Gauge(name, tags)
}
return gauge
}
// Namespace implements metrics.Factory interface
func (f *Factory) Namespace(name string, tags map[string]string) metrics.Factory {
newFactory := &Factory{
factories: make([]metrics.Factory, len(f.factories)),
}
for i, factory := range f.factories {
newFactory.factories[i] = factory.Namespace(name, tags)
}
return newFactory
}
-85
View File
@@ -1,85 +0,0 @@
// Copyright (c) 2017 The Jaeger Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package prometheus
import (
"strings"
"sync"
"github.com/prometheus/client_golang/prometheus"
)
type vectorCache struct {
registerer prometheus.Registerer
lock sync.Mutex
cVecs map[string]*prometheus.CounterVec
gVecs map[string]*prometheus.GaugeVec
hVecs map[string]*prometheus.HistogramVec
}
func newVectorCache(registerer prometheus.Registerer) *vectorCache {
return &vectorCache{
registerer: registerer,
cVecs: make(map[string]*prometheus.CounterVec),
gVecs: make(map[string]*prometheus.GaugeVec),
hVecs: make(map[string]*prometheus.HistogramVec),
}
}
func (c *vectorCache) getOrMakeCounterVec(opts prometheus.CounterOpts, labelNames []string) *prometheus.CounterVec {
c.lock.Lock()
defer c.lock.Unlock()
cacheKey := c.getCacheKey(opts.Name, labelNames)
cv, cvExists := c.cVecs[cacheKey]
if !cvExists {
cv = prometheus.NewCounterVec(opts, labelNames)
c.registerer.MustRegister(cv)
c.cVecs[cacheKey] = cv
}
return cv
}
func (c *vectorCache) getOrMakeGaugeVec(opts prometheus.GaugeOpts, labelNames []string) *prometheus.GaugeVec {
c.lock.Lock()
defer c.lock.Unlock()
cacheKey := c.getCacheKey(opts.Name, labelNames)
gv, gvExists := c.gVecs[cacheKey]
if !gvExists {
gv = prometheus.NewGaugeVec(opts, labelNames)
c.registerer.MustRegister(gv)
c.gVecs[cacheKey] = gv
}
return gv
}
func (c *vectorCache) getOrMakeHistogramVec(opts prometheus.HistogramOpts, labelNames []string) *prometheus.HistogramVec {
c.lock.Lock()
defer c.lock.Unlock()
cacheKey := c.getCacheKey(opts.Name, labelNames)
hv, hvExists := c.hVecs[cacheKey]
if !hvExists {
hv = prometheus.NewHistogramVec(opts, labelNames)
c.registerer.MustRegister(hv)
c.hVecs[cacheKey] = hv
}
return hv
}
func (c *vectorCache) getCacheKey(name string, labels []string) string {
return strings.Join(append([]string{name}, labels...), "||")
}
-216
View File
@@ -1,216 +0,0 @@
// Copyright (c) 2017 The Jaeger Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package prometheus
import (
"sort"
"strings"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/uber/jaeger-lib/metrics"
)
// Factory implements metrics.Factory backed by Prometheus registry.
type Factory struct {
scope string
tags map[string]string
cache *vectorCache
buckets []float64
normalizer *strings.Replacer
}
type options struct {
registerer prometheus.Registerer
buckets []float64
}
// Option is a function that sets some option for the Factory constructor.
type Option func(*options)
// WithRegisterer returns an option that sets the registerer.
// If not used we fallback to prometheus.DefaultRegisterer.
func WithRegisterer(registerer prometheus.Registerer) Option {
return func(opts *options) {
opts.registerer = registerer
}
}
// WithBuckets returns an option that sets the default buckets for histogram.
// If not used, we fallback to default Prometheus buckets.
func WithBuckets(buckets []float64) Option {
return func(opts *options) {
opts.buckets = buckets
}
}
func applyOptions(opts []Option) *options {
options := new(options)
for _, o := range opts {
o(options)
}
if options.registerer == nil {
options.registerer = prometheus.DefaultRegisterer
}
return options
}
// New creates a Factory backed by Prometheus registry.
// Typically the first argument should be prometheus.DefaultRegisterer.
//
// Parameter buckets defines the buckets into which Timer observations are counted.
// Each element in the slice is the upper inclusive bound of a bucket. The
// values must be sorted in strictly increasing order. There is no need
// to add a highest bucket with +Inf bound, it will be added
// implicitly. The default value is prometheus.DefBuckets.
func New(opts ...Option) *Factory {
options := applyOptions(opts)
return newFactory(
&Factory{ // dummy struct to be discarded
cache: newVectorCache(options.registerer),
buckets: options.buckets,
normalizer: strings.NewReplacer(".", "_", "-", "_"),
},
"", // scope
nil) // tags
}
func newFactory(parent *Factory, scope string, tags map[string]string) *Factory {
return &Factory{
cache: parent.cache,
buckets: parent.buckets,
normalizer: parent.normalizer,
scope: scope,
tags: tags,
}
}
// Counter implements Counter of metrics.Factory.
func (f *Factory) Counter(name string, tags map[string]string) metrics.Counter {
name = f.subScope(name)
tags = f.mergeTags(tags)
labelNames := f.tagNames(tags)
opts := prometheus.CounterOpts{
Name: name,
Help: name,
}
cv := f.cache.getOrMakeCounterVec(opts, labelNames)
return &counter{
counter: cv.WithLabelValues(f.tagsAsLabelValues(labelNames, tags)...),
}
}
// Gauge implements Gauge of metrics.Factory.
func (f *Factory) Gauge(name string, tags map[string]string) metrics.Gauge {
name = f.subScope(name)
tags = f.mergeTags(tags)
labelNames := f.tagNames(tags)
opts := prometheus.GaugeOpts{
Name: name,
Help: name,
}
gv := f.cache.getOrMakeGaugeVec(opts, labelNames)
return &gauge{
gauge: gv.WithLabelValues(f.tagsAsLabelValues(labelNames, tags)...),
}
}
// Timer implements Timer of metrics.Factory.
func (f *Factory) Timer(name string, tags map[string]string) metrics.Timer {
name = f.subScope(name)
tags = f.mergeTags(tags)
labelNames := f.tagNames(tags)
opts := prometheus.HistogramOpts{
Name: name,
Help: name,
Buckets: f.buckets,
}
hv := f.cache.getOrMakeHistogramVec(opts, labelNames)
return &timer{
histogram: hv.WithLabelValues(f.tagsAsLabelValues(labelNames, tags)...),
}
}
// Namespace implements Namespace of metrics.Factory.
func (f *Factory) Namespace(name string, tags map[string]string) metrics.Factory {
return newFactory(f, f.subScope(name), f.mergeTags(tags))
}
type counter struct {
counter prometheus.Counter
}
func (c *counter) Inc(v int64) {
c.counter.Add(float64(v))
}
type gauge struct {
gauge prometheus.Gauge
}
func (g *gauge) Update(v int64) {
g.gauge.Set(float64(v))
}
type timer struct {
histogram prometheus.Histogram
}
func (t *timer) Record(v time.Duration) {
t.histogram.Observe(float64(v.Nanoseconds()) / float64(time.Second/time.Nanosecond))
}
func (f *Factory) subScope(name string) string {
if f.scope == "" {
return f.normalize(name)
}
if name == "" {
return f.normalize(f.scope)
}
return f.normalize(f.scope + ":" + name)
}
func (f *Factory) normalize(v string) string {
return f.normalizer.Replace(v)
}
func (f *Factory) mergeTags(tags map[string]string) map[string]string {
ret := make(map[string]string, len(f.tags)+len(tags))
for k, v := range f.tags {
ret[k] = v
}
for k, v := range tags {
ret[k] = v
}
return ret
}
func (f *Factory) tagNames(tags map[string]string) []string {
ret := make([]string, 0, len(tags))
for k := range tags {
ret = append(ret, k)
}
sort.Strings(ret)
return ret
}
func (f *Factory) tagsAsLabelValues(labels []string, tags map[string]string) []string {
ret := make([]string, 0, len(tags))
for _, l := range labels {
ret = append(ret, tags[l])
}
return ret
}
-63
View File
@@ -1,63 +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 tally
import (
"github.com/uber-go/tally"
"github.com/uber/jaeger-lib/metrics"
)
// Wrap takes a tally Scope and returns jaeger-lib metrics.Factory.
func Wrap(scope tally.Scope) metrics.Factory {
return &factory{
tally: scope,
}
}
// TODO implement support for tags if tally.Scope does not support them
type factory struct {
tally tally.Scope
}
func (f *factory) Counter(name string, tags map[string]string) metrics.Counter {
scope := f.tally
if len(tags) > 0 {
scope = scope.Tagged(tags)
}
return NewCounter(scope.Counter(name))
}
func (f *factory) Gauge(name string, tags map[string]string) metrics.Gauge {
scope := f.tally
if len(tags) > 0 {
scope = scope.Tagged(tags)
}
return NewGauge(scope.Gauge(name))
}
func (f *factory) Timer(name string, tags map[string]string) metrics.Timer {
scope := f.tally
if len(tags) > 0 {
scope = scope.Tagged(tags)
}
return NewTimer(scope.Timer(name))
}
func (f *factory) Namespace(name string, tags map[string]string) metrics.Factory {
return &factory{
tally: f.tally.SubScope(name).Tagged(tags),
}
}
-66
View File
@@ -1,66 +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 tally
import (
"time"
"github.com/uber-go/tally"
)
// Counter is an adapter from go-tally Counter to jaeger-lib Counter
type Counter struct {
counter tally.Counter
}
// NewCounter creates a new Counter
func NewCounter(counter tally.Counter) *Counter {
return &Counter{counter: counter}
}
// Inc adds the given value to the counter.
func (c *Counter) Inc(delta int64) {
c.counter.Inc(delta)
}
// Gauge is an adapter from go-tally Gauge to jaeger-lib Gauge
type Gauge struct {
gauge tally.Gauge
}
// NewGauge creates a new Gauge
func NewGauge(gauge tally.Gauge) *Gauge {
return &Gauge{gauge: gauge}
}
// Update the gauge to the value passed in.
func (g *Gauge) Update(value int64) {
g.gauge.Update(float64(value))
}
// Timer is an adapter from go-tally Histogram to jaeger-lib Timer
type Timer struct {
timer tally.Timer
}
// NewTimer creates a new Timer
func NewTimer(timer tally.Timer) *Timer {
return &Timer{timer: timer}
}
// Record saves the time passed in.
func (t *Timer) Record(delta time.Duration) {
t.timer.Record(delta)
}
-55
View File
@@ -1,55 +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 (
"testing"
"github.com/stretchr/testify/assert"
"github.com/uber/jaeger-lib/metrics"
)
// ExpectedMetric contains metrics under test.
type ExpectedMetric struct {
Name string
Tags map[string]string
Value int
}
// TODO do something similar for Timers
// AssertCounterMetrics checks if counter metrics exist.
func AssertCounterMetrics(t *testing.T, f *metrics.LocalFactory, expectedMetrics ...ExpectedMetric) {
counters, _ := f.Snapshot()
assertMetrics(t, counters, expectedMetrics...)
}
// AssertGaugeMetrics checks if gauge metrics exist.
func AssertGaugeMetrics(t *testing.T, f *metrics.LocalFactory, expectedMetrics ...ExpectedMetric) {
_, gauges := f.Snapshot()
assertMetrics(t, gauges, expectedMetrics...)
}
func assertMetrics(t *testing.T, actualMetrics map[string]int64, expectedMetrics ...ExpectedMetric) {
for _, expected := range expectedMetrics {
key := metrics.GetKey(expected.Name, expected.Tags, "|", "=")
assert.EqualValues(t,
expected.Value,
actualMetrics[key],
"expected metric name: %s, tags: %+v", expected.Name, expected.Tags,
)
}
}
-24
View File
@@ -1,24 +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 sample
import (
"fmt"
)
// SayHello is a sample function
func SayHello() {
fmt.Println("Hello, playground")
}
-64
View File
@@ -1,64 +0,0 @@
#!/bin/bash
set -e
COVER=.cover
ROOT_PKG=github.com/uber/jaeger-lib/
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
if [[ "$filter" = "" ]]; then
# make up some name to avoid breaking jq's select(in({}))
filter='"no-filter": true'
fi
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
-6
View File
@@ -1,6 +0,0 @@
#!/bin/bash
set -e
set -x
python scripts/updateLicense.py $(go list -json $(glide nv) | jq -r '.Dir + "/" + (.GoFiles | .[])')
-77
View File
@@ -1,77 +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 utils
import (
"sync"
"time"
)
// RateLimiter is a filter used to check if a message that is worth itemCost units is within the rate limits.
type RateLimiter interface {
CheckCredit(itemCost float64) bool
}
type rateLimiter struct {
sync.Mutex
creditsPerSecond float64
balance float64
maxBalance float64
lastTick time.Time
timeNow func() time.Time
}
// NewRateLimiter creates a new rate limiter based on leaky bucket algorithm, formulated in terms of a
// credits balance that is replenished every time CheckCredit() method is called (tick) by the amount proportional
// to the time elapsed since the last tick, up to max of creditsPerSecond. A call to CheckCredit() takes a cost
// of an item we want to pay with the balance. If the balance exceeds the cost of the item, the item is "purchased"
// and the balance reduced, indicated by returned value of true. Otherwise the balance is unchanged and return false.
//
// This can be used to limit a rate of messages emitted by a service by instantiating the Rate Limiter with the
// max number of messages a service is allowed to emit per second, and calling CheckCredit(1.0) for each message
// to determine if the message is within the rate limit.
//
// It can also be used to limit the rate of traffic in bytes, by setting creditsPerSecond to desired throughput
// as bytes/second, and calling CheckCredit() with the actual message size.
func NewRateLimiter(creditsPerSecond, maxBalance float64) RateLimiter {
return &rateLimiter{
creditsPerSecond: creditsPerSecond,
balance: maxBalance,
maxBalance: maxBalance,
lastTick: time.Now(),
timeNow: time.Now}
}
func (b *rateLimiter) CheckCredit(itemCost float64) bool {
b.Lock()
defer b.Unlock()
// calculate how much time passed since the last tick, and update current tick
currentTime := b.timeNow()
elapsedTime := currentTime.Sub(b.lastTick)
b.lastTick = currentTime
// calculate how much credit have we accumulated since the last tick
b.balance += elapsedTime.Seconds() * b.creditsPerSecond
if b.balance > b.maxBalance {
b.balance = b.maxBalance
}
// if we have enough credits to pay for current item, then reduce balance and allow
if b.balance >= itemCost {
b.balance -= itemCost
return true
}
return false
}