1// Copyright (c) 2017 Uber Technologies, Inc. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package server 16 17import ( 18 "context" 19 "fmt" 20 21 "github.com/opentracing/opentracing-go" 22 "github.com/opentracing/opentracing-go/ext" 23 24 "github.com/uber/jaeger-client-go" 25 "github.com/uber/jaeger-client-go/crossdock/common" 26 "github.com/uber/jaeger-client-go/crossdock/log" 27 "github.com/uber/jaeger-client-go/crossdock/thrift/tracetest" 28) 29 30func (s *Server) doStartTrace(req *tracetest.StartTraceRequest) (*tracetest.TraceResponse, error) { 31 span := s.Tracer.StartSpan(req.ServerRole) 32 if req.Sampled { 33 ext.SamplingPriority.Set(span, 1) 34 } 35 span.SetBaggageItem(BaggageKey, req.Baggage) 36 defer span.Finish() 37 38 ctx := opentracing.ContextWithSpan(context.Background(), span) 39 40 return s.prepareResponse(ctx, req.ServerRole, req.Downstream) 41} 42 43func (s *Server) doJoinTrace(ctx context.Context, req *tracetest.JoinTraceRequest) (*tracetest.TraceResponse, error) { 44 return s.prepareResponse(ctx, req.ServerRole, req.Downstream) 45} 46 47func (s *Server) prepareResponse(ctx context.Context, role string, reqDwn *tracetest.Downstream) (*tracetest.TraceResponse, error) { 48 observedSpan, err := observeSpan(ctx, s.Tracer) 49 if err != nil { 50 return nil, err 51 } 52 53 resp := tracetest.NewTraceResponse() 54 resp.Span = observedSpan 55 56 if reqDwn != nil { 57 downstreamResp, err := s.callDownstream(ctx, role, reqDwn) 58 if err != nil { 59 return nil, err 60 } 61 resp.Downstream = downstreamResp 62 } 63 64 return resp, nil 65} 66 67func (s *Server) callDownstream(ctx context.Context, role string, downstream *tracetest.Downstream) (*tracetest.TraceResponse, error) { 68 switch downstream.Transport { 69 case tracetest.Transport_HTTP: 70 return s.callDownstreamHTTP(ctx, downstream) 71 case tracetest.Transport_DUMMY: 72 return &tracetest.TraceResponse{NotImplementedError: "DUMMY transport not implemented"}, nil 73 default: 74 return nil, errUnrecognizedProtocol 75 } 76} 77 78func (s *Server) callDownstreamHTTP(ctx context.Context, target *tracetest.Downstream) (*tracetest.TraceResponse, error) { 79 req := &tracetest.JoinTraceRequest{ 80 ServerRole: target.ServerRole, 81 Downstream: target.Downstream, 82 } 83 url := fmt.Sprintf("http://%s:%s/join_trace", target.Host, target.Port) 84 log.Printf("Calling downstream service '%s' at %s", target.ServiceName, url) 85 return common.PostJSON(ctx, url, req) 86} 87 88func observeSpan(ctx context.Context, tracer opentracing.Tracer) (*tracetest.ObservedSpan, error) { 89 span := opentracing.SpanFromContext(ctx) 90 if span == nil { 91 return nil, errNoSpanObserved 92 } 93 sc := span.Context().(jaeger.SpanContext) 94 observedSpan := tracetest.NewObservedSpan() 95 observedSpan.TraceId = sc.TraceID().String() 96 observedSpan.Sampled = sc.IsSampled() 97 observedSpan.Baggage = span.BaggageItem(BaggageKey) 98 return observedSpan, nil 99} 100