func (b *Behavior) prepareResponse(t crossdock.T, ctx context.Context, reqDwn *Downstream) (*Response, error) { log.Printf("prepareResponse: reqDwn=%v", reqDwn) logSpan(ctx) observedSpan, err := observeSpan(ctx) if err != nil { return nil, err } resp := &Response{ Span: observedSpan, } if reqDwn != nil { downstreamResp, err := b.callDownstream(ctx, reqDwn) if err != nil { if t != nil { t.Errorf("Error when calling downstream %+v: %s", reqDwn, err) } return nil, err } resp.Downstream = downstreamResp } return resp, nil }
// Run executes the trace behavior func (b *Behavior) Run(t crossdock.T) { logParams(t) sampled, err := strconv.ParseBool(t.Param(sampledParam)) if err != nil { t.Fatalf("Malformed param %s: %s", sampledParam, err) } baggage := randomBaggage() level1 := &Request{ ServerRole: RoleS1, } server1 := t.Param(server1NameParam) level2 := &Downstream{ ServiceName: t.Param(server2NameParam), ServerRole: RoleS2, HostPort: fmt.Sprintf("%s:%s", b.serviceToHost(t.Param(server2NameParam)), b.ServerPort, ), Encoding: t.Param(server2EncodingParam), } level1.Downstream = level2 level3 := &Downstream{ ServiceName: t.Param(server3NameParam), ServerRole: RoleS3, HostPort: fmt.Sprintf("%s:%s", b.serviceToHost(t.Param(server3NameParam)), b.ServerPort, ), Encoding: t.Param(server3EncodingParam), } level2.Downstream = level3 resp, err := b.startTrace(t, level1, sampled, baggage) if err != nil { t.Errorf("Failed to startTrace in S1(%s): %s", server1, err.Error()) return } log.Printf("Response: span=%+v, downstream=%+v", resp.Span, resp.Downstream) traceID := resp.Span.TraceID require := crossdock.Require(t) require.NotEmpty(traceID, "Trace ID should not be empty in S1(%s)", server1) if validateTrace(t, level1.Downstream, resp, server1, 1, traceID, sampled, baggage) { t.Successf("trace checks out") log.Println("PASS") } else { log.Println("FAIL") } }
func (h *jsonHandler) callDownstream(ctx context.Context, target *Downstream) (*Response, error) { req := &Request{ ServerRole: target.ServerRole, Downstream: target.Downstream, } jctx := json.Wrap(ctx) response := new(Response) log.Printf("Calling JSON service %s (%s)", target.ServiceName, target.HostPort) peer := h.ch.Peers().GetOrAdd(target.HostPort) if err := json.CallPeer(jctx, peer, target.ServiceName, jsonEndpoint, req, response); err != nil { return nil, err } return response, nil }
func observeSpan(ctx context.Context) (*ObservedSpan, error) { span := opentracing.SpanFromContext(ctx) if span == nil { return nil, errNoSpanObserved } sc, ok := span.Context().(jaeger.SpanContext) if !ok { return &ObservedSpan{}, nil } observedSpan := &ObservedSpan{ TraceID: fmt.Sprintf("%x", sc.TraceID()), Sampled: sc.IsSampled(), Baggage: span.BaggageItem(BaggageKey), } log.Printf("Observed span %+v", observedSpan) return observedSpan, nil }
// Start starts the test server called by the Client and other upstream servers. func (s *Server) Start() error { if s.HostPort == "" { s.HostPort = ":" + common.DefaultServerPort } channelOpts := &tchannel.ChannelOptions{ Tracer: s.Tracer, } ch, err := tchannel.NewChannel(common.DefaultServiceName, channelOpts) if err != nil { return err } if err := ch.ListenAndServe(s.HostPort); err != nil { return err } s.HostPort = ch.PeerInfo().HostPort // override in case it was ":0" log.Printf("Started tchannel server at %s\n", s.HostPort) s.Ch = ch return nil }
func (h *thriftHandler) callDownstream(ctx context.Context, target *Downstream) (*Response, error) { req := &Request{ ServerRole: target.ServerRole, Downstream: target.Downstream, } opts := &thrift.ClientOptions{HostPort: target.HostPort} thriftClient := thrift.NewClient(h.ch, target.ServiceName, opts) serviceClient := gen.NewTChanSimpleServiceClient(thriftClient) tReq, err := requestToThrift(req) if err != nil { return nil, err } log.Printf("Calling Thrift service %s (%s)", target.ServiceName, target.HostPort) tctx := thrift.Wrap(ctx) res, err := serviceClient.Call(tctx, tReq) if err != nil { return nil, err } return responseFromThrift(res) }
func logSpan(ctx context.Context) { if span := opentracing.SpanFromContext(ctx); span != nil { log.Printf("Span %s", span) } }