| @@ -10,6 +10,7 @@ import ( | ||||
| 	"github.com/micro/go-micro/broker" | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/client/selector" | ||||
| 	"github.com/micro/go-micro/debug/trace" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/runtime" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| @@ -22,9 +23,9 @@ import ( | ||||
| 	cmucp "github.com/micro/go-micro/client/mucp" | ||||
|  | ||||
| 	// servers | ||||
| 	"github.com/micro/cli/v2" | ||||
| 	sgrpc "github.com/micro/go-micro/server/grpc" | ||||
| 	smucp "github.com/micro/go-micro/server/mucp" | ||||
| 	"github.com/micro/cli/v2" | ||||
|  | ||||
| 	// brokers | ||||
| 	"github.com/micro/go-micro/broker/memory" | ||||
| @@ -50,6 +51,10 @@ import ( | ||||
| 	// stores | ||||
| 	memStore "github.com/micro/go-micro/store/memory" | ||||
| 	svcStore "github.com/micro/go-micro/store/service" | ||||
|  | ||||
| 	// tracers | ||||
| 	// jTracer "github.com/micro/go-micro/debug/trace/jaeger" | ||||
| 	memTracer "github.com/micro/go-micro/debug/trace/memory" | ||||
| ) | ||||
|  | ||||
| type Cmd interface { | ||||
| @@ -208,6 +213,16 @@ var ( | ||||
| 			EnvVars: []string{"MICRO_TRANSPORT_ADDRESS"}, | ||||
| 			Usage:   "Comma-separated list of transport addresses", | ||||
| 		}, | ||||
| 		&cli.StringFlag{ | ||||
| 			Name:    "tracer", | ||||
| 			EnvVars: []string{"MICRO_TRACER"}, | ||||
| 			Usage:   "Tracer for distributed tracing, e.g. memory, jaeger", | ||||
| 		}, | ||||
| 		&cli.StringFlag{ | ||||
| 			Name:    "tracer_address", | ||||
| 			EnvVars: []string{"MICRO_TRACER_ADDRESS"}, | ||||
| 			Usage:   "Comma-separated list of tracer addresses", | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	DefaultBrokers = map[string]func(...broker.Option) broker.Broker{ | ||||
| @@ -254,6 +269,11 @@ var ( | ||||
| 		"service": svcStore.NewStore, | ||||
| 	} | ||||
|  | ||||
| 	DefaultTracers = map[string]func(...trace.Option) trace.Tracer{ | ||||
| 		"memory": memTracer.NewTracer, | ||||
| 		// "jaeger": jTracer.NewTracer, | ||||
| 	} | ||||
|  | ||||
| 	// used for default selection as the fall back | ||||
| 	defaultClient    = "grpc" | ||||
| 	defaultServer    = "grpc" | ||||
| @@ -279,6 +299,7 @@ func newCmd(opts ...Option) Cmd { | ||||
| 		Transport: &transport.DefaultTransport, | ||||
| 		Runtime:   &runtime.DefaultRuntime, | ||||
| 		Store:     &store.DefaultStore, | ||||
| 		Tracer:    &trace.DefaultTracer, | ||||
|  | ||||
| 		Brokers:    DefaultBrokers, | ||||
| 		Clients:    DefaultClients, | ||||
| @@ -288,6 +309,7 @@ func newCmd(opts ...Option) Cmd { | ||||
| 		Transports: DefaultTransports, | ||||
| 		Runtimes:   DefaultRuntimes, | ||||
| 		Stores:     DefaultStores, | ||||
| 		Tracers:    DefaultTracers, | ||||
| 	} | ||||
|  | ||||
| 	for _, o := range opts { | ||||
| @@ -330,7 +352,7 @@ func (c *cmd) Before(ctx *cli.Context) error { | ||||
| 	var serverOpts []server.Option | ||||
| 	var clientOpts []client.Option | ||||
|  | ||||
| 	// Set the runtime | ||||
| 	// Set the store | ||||
| 	if name := ctx.String("store"); len(name) > 0 { | ||||
| 		s, ok := c.opts.Stores[name] | ||||
| 		if !ok { | ||||
| @@ -350,6 +372,16 @@ func (c *cmd) Before(ctx *cli.Context) error { | ||||
| 		*c.opts.Runtime = r() | ||||
| 	} | ||||
|  | ||||
| 	// Set the tracer | ||||
| 	if name := ctx.String("tracer"); len(name) > 0 { | ||||
| 		r, ok := c.opts.Tracers[name] | ||||
| 		if !ok { | ||||
| 			return fmt.Errorf("Unsupported tracer: %s", name) | ||||
| 		} | ||||
|  | ||||
| 		*c.opts.Tracer = r() | ||||
| 	} | ||||
|  | ||||
| 	// Set the client | ||||
| 	if name := ctx.String("client"); len(name) > 0 { | ||||
| 		// only change if we have the client and type differs | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
| 	"github.com/micro/go-micro/broker" | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/client/selector" | ||||
| 	"github.com/micro/go-micro/debug/trace" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/runtime" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| @@ -28,6 +29,7 @@ type Options struct { | ||||
| 	Server    *server.Server | ||||
| 	Runtime   *runtime.Runtime | ||||
| 	Store     *store.Store | ||||
| 	Tracer    *trace.Tracer | ||||
|  | ||||
| 	Brokers    map[string]func(...broker.Option) broker.Broker | ||||
| 	Clients    map[string]func(...client.Option) client.Client | ||||
| @@ -37,6 +39,7 @@ type Options struct { | ||||
| 	Transports map[string]func(...transport.Option) transport.Transport | ||||
| 	Runtimes   map[string]func(...runtime.Option) runtime.Runtime | ||||
| 	Stores     map[string]func(...store.Option) store.Store | ||||
| 	Tracers    map[string]func(...trace.Option) trace.Tracer | ||||
|  | ||||
| 	// Other options for implementations of the interface | ||||
| 	// can be stored in a context | ||||
| @@ -100,6 +103,12 @@ func Server(s *server.Server) Option { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Tracer(t *trace.Tracer) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Tracer = t | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // New broker func | ||||
| func NewBroker(name string, b func(...broker.Option) broker.Broker) Option { | ||||
| 	return func(o *Options) { | ||||
| @@ -148,3 +157,10 @@ func NewRuntime(name string, r func(...runtime.Option) runtime.Runtime) Option { | ||||
| 		o.Runtimes[name] = r | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // New tracer func | ||||
| func NewTracer(name string, t func(...trace.Option) trace.Tracer) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Tracers[name] = t | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -12,10 +12,14 @@ import ( | ||||
| 	"github.com/micro/go-micro/server" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// DefaultHandler is default debug handler | ||||
| 	DefaultHandler = newDebug() | ||||
| ) | ||||
| // NewHandler returns an instance of the Debug Handler | ||||
| func NewHandler(srv server.Server) *Debug { | ||||
| 	return &Debug{ | ||||
| 		log:   log.DefaultLog, | ||||
| 		stats: stats.DefaultStats, | ||||
| 		trace: srv.Options().Tracer, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type Debug struct { | ||||
| 	// must honour the debug handler | ||||
| @@ -25,15 +29,7 @@ type Debug struct { | ||||
| 	// the stats collector | ||||
| 	stats stats.Stats | ||||
| 	// the tracer | ||||
| 	trace trace.Trace | ||||
| } | ||||
|  | ||||
| func newDebug() *Debug { | ||||
| 	return &Debug{ | ||||
| 		log:   log.DefaultLog, | ||||
| 		stats: stats.DefaultStats, | ||||
| 		trace: trace.DefaultTrace, | ||||
| 	} | ||||
| 	trace trace.Tracer | ||||
| } | ||||
|  | ||||
| func (d *Debug) Health(ctx context.Context, req *proto.HealthRequest, rsp *proto.HealthResponse) error { | ||||
|   | ||||
| @@ -1,32 +1,33 @@ | ||||
| package trace | ||||
| package memory | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/google/uuid" | ||||
| 	"github.com/micro/go-micro/debug/trace" | ||||
| 	"github.com/micro/go-micro/util/ring" | ||||
| ) | ||||
| 
 | ||||
| type trace struct { | ||||
| 	opts Options | ||||
| type Tracer struct { | ||||
| 	opts trace.Options | ||||
| 
 | ||||
| 	// ring buffer of traces | ||||
| 	buffer *ring.Buffer | ||||
| } | ||||
| 
 | ||||
| func (t *trace) Read(opts ...ReadOption) ([]*Span, error) { | ||||
| 	var options ReadOptions | ||||
| func (t *Tracer) Read(opts ...trace.ReadOption) ([]*trace.Span, error) { | ||||
| 	var options trace.ReadOptions | ||||
| 	for _, o := range opts { | ||||
| 		o(&options) | ||||
| 	} | ||||
| 
 | ||||
| 	sp := t.buffer.Get(t.buffer.Size()) | ||||
| 
 | ||||
| 	var spans []*Span | ||||
| 	var spans []*trace.Span | ||||
| 
 | ||||
| 	for _, span := range sp { | ||||
| 		val := span.Value.(*Span) | ||||
| 		val := span.Value.(*trace.Span) | ||||
| 		// skip if trace id is specified and doesn't match | ||||
| 		if len(options.Trace) > 0 && val.Trace != options.Trace { | ||||
| 			continue | ||||
| @@ -37,8 +38,8 @@ func (t *trace) Read(opts ...ReadOption) ([]*Span, error) { | ||||
| 	return spans, nil | ||||
| } | ||||
| 
 | ||||
| func (t *trace) Start(ctx context.Context, name string) (context.Context, *Span) { | ||||
| 	span := &Span{ | ||||
| func (t *Tracer) Start(ctx context.Context, name string) (context.Context, *trace.Span) { | ||||
| 	span := &trace.Span{ | ||||
| 		Name:     name, | ||||
| 		Trace:    uuid.New().String(), | ||||
| 		Id:       uuid.New().String(), | ||||
| @@ -51,7 +52,7 @@ func (t *trace) Start(ctx context.Context, name string) (context.Context, *Span) | ||||
| 		return context.Background(), span | ||||
| 	} | ||||
| 
 | ||||
| 	s, ok := FromContext(ctx) | ||||
| 	s, ok := trace.FromContext(ctx) | ||||
| 	if !ok { | ||||
| 		return ctx, span | ||||
| 	} | ||||
| @@ -65,7 +66,7 @@ func (t *trace) Start(ctx context.Context, name string) (context.Context, *Span) | ||||
| 	return ctx, span | ||||
| } | ||||
| 
 | ||||
| func (t *trace) Finish(s *Span) error { | ||||
| func (t *Tracer) Finish(s *trace.Span) error { | ||||
| 	// set finished time | ||||
| 	s.Duration = time.Since(s.Started) | ||||
| 
 | ||||
| @@ -75,13 +76,13 @@ func (t *trace) Finish(s *Span) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func NewTrace(opts ...Option) Trace { | ||||
| 	var options Options | ||||
| func NewTracer(opts ...trace.Option) trace.Tracer { | ||||
| 	var options trace.Options | ||||
| 	for _, o := range opts { | ||||
| 		o(&options) | ||||
| 	} | ||||
| 
 | ||||
| 	return &trace{ | ||||
| 	return &Tracer{ | ||||
| 		opts: options, | ||||
| 		// the last 64 requests | ||||
| 		buffer: ring.New(64), | ||||
| @@ -1,6 +1,9 @@ | ||||
| package trace | ||||
|  | ||||
| type Options struct{} | ||||
| type Options struct { | ||||
| 	// Size is the size of ring buffer | ||||
| 	Size int | ||||
| } | ||||
|  | ||||
| type Option func(o *Options) | ||||
|  | ||||
| @@ -17,3 +20,15 @@ func ReadTrace(t string) ReadOption { | ||||
| 		o.Trace = t | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	// DefaultSize of the buffer | ||||
| 	DefaultSize = 64 | ||||
| ) | ||||
|  | ||||
| // DefaultOptions returns default options | ||||
| func DefaultOptions() Options { | ||||
| 	return Options{ | ||||
| 		Size: DefaultSize, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -6,8 +6,8 @@ import ( | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| // Trace is an interface for distributed tracing | ||||
| type Trace interface { | ||||
| // Tracer is an interface for distributed tracing | ||||
| type Tracer interface { | ||||
| 	// Start a trace | ||||
| 	Start(ctx context.Context, name string) (context.Context, *Span) | ||||
| 	// Finish the trace | ||||
| @@ -36,11 +36,6 @@ type Span struct { | ||||
|  | ||||
| type spanKey struct{} | ||||
|  | ||||
| var ( | ||||
| 	// Default tracer | ||||
| 	DefaultTrace = NewTrace() | ||||
| ) | ||||
|  | ||||
| // FromContext returns a span from context | ||||
| func FromContext(ctx context.Context) (*Span, bool) { | ||||
| 	s, ok := ctx.Value(spanKey{}).(*Span) | ||||
| @@ -51,3 +46,25 @@ func FromContext(ctx context.Context) (*Span, bool) { | ||||
| func NewContext(ctx context.Context, s *Span) context.Context { | ||||
| 	return context.WithValue(ctx, spanKey{}, s) | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	DefaultTracer Tracer = new(noop) | ||||
| ) | ||||
|  | ||||
| type noop struct{} | ||||
|  | ||||
| func (n *noop) Init(...Option) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (n *noop) Start(ctx context.Context, name string) (context.Context, *Span) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (n *noop) Finish(*Span) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (n *noop) Read(...ReadOption) ([]*Span, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										10
									
								
								options.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								options.go
									
									
									
									
									
								
							| @@ -4,14 +4,15 @@ import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/micro/cli/v2" | ||||
| 	"github.com/micro/go-micro/broker" | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/client/selector" | ||||
| 	"github.com/micro/go-micro/config/cmd" | ||||
| 	"github.com/micro/go-micro/debug/trace" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| 	"github.com/micro/go-micro/transport" | ||||
| 	"github.com/micro/cli/v2" | ||||
| ) | ||||
|  | ||||
| type Options struct { | ||||
| @@ -112,6 +113,13 @@ func Registry(r registry.Registry) Option { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Tracer sets the tracer for the service | ||||
| func Tracer(t trace.Tracer) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.Tracer(t)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Selector sets the selector for the service client | ||||
| func Selector(s selector.Selector) Option { | ||||
| 	return func(o *Options) { | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
|  | ||||
| 	"github.com/micro/go-micro/broker" | ||||
| 	"github.com/micro/go-micro/codec" | ||||
| 	"github.com/micro/go-micro/debug/trace" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/transport" | ||||
| ) | ||||
| @@ -15,6 +16,7 @@ type Options struct { | ||||
| 	Codecs       map[string]codec.NewCodec | ||||
| 	Broker       broker.Broker | ||||
| 	Registry     registry.Registry | ||||
| 	Tracer       trace.Tracer | ||||
| 	Transport    transport.Transport | ||||
| 	Metadata     map[string]string | ||||
| 	Name         string | ||||
| @@ -152,6 +154,13 @@ func Registry(r registry.Registry) Option { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Tracer mechanism for distributed tracking | ||||
| func Tracer(t trace.Tracer) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Tracer = t | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Transport mechanism for communication e.g http, rabbitmq, etc | ||||
| func Transport(t transport.Transport) Option { | ||||
| 	return func(o *Options) { | ||||
|   | ||||
							
								
								
									
										10
									
								
								service.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								service.go
									
									
									
									
									
								
							| @@ -15,7 +15,6 @@ import ( | ||||
| 	"github.com/micro/go-micro/debug/profile/pprof" | ||||
| 	"github.com/micro/go-micro/debug/service/handler" | ||||
| 	"github.com/micro/go-micro/debug/stats" | ||||
| 	"github.com/micro/go-micro/debug/trace" | ||||
| 	"github.com/micro/go-micro/plugin" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| 	"github.com/micro/go-micro/util/log" | ||||
| @@ -36,17 +35,14 @@ func newService(opts ...Option) Service { | ||||
|  | ||||
| 	// wrap client to inject From-Service header on any calls | ||||
| 	options.Client = wrapper.FromService(serviceName, options.Client) | ||||
|  | ||||
| 	// wrap client to inject From-Service header on any calls | ||||
| 	options.Client = wrapper.TraceCall(serviceName, trace.DefaultTrace, options.Client) | ||||
| 	options.Client = wrapper.TraceCall(serviceName, options.Server.Options().Tracer, options.Client) | ||||
|  | ||||
| 	// wrap the server to provide handler stats | ||||
| 	options.Server.Init( | ||||
| 		server.WrapHandler(wrapper.HandlerStats(stats.DefaultStats)), | ||||
| 		server.WrapHandler(wrapper.TraceHandler(trace.DefaultTrace)), | ||||
| 		server.WrapHandler(wrapper.TraceHandler(options.Server.Options().Tracer)), | ||||
| 	) | ||||
|  | ||||
|  | ||||
| 	return &service{ | ||||
| 		opts: options, | ||||
| 	} | ||||
| @@ -162,7 +158,7 @@ func (s *service) Run() error { | ||||
| 	// register the debug handler | ||||
| 	s.opts.Server.Handle( | ||||
| 		s.opts.Server.NewHandler( | ||||
| 			handler.DefaultHandler, | ||||
| 			handler.NewHandler(s.Options().Server), | ||||
| 			server.InternalHandler(true), | ||||
| 		), | ||||
| 	) | ||||
|   | ||||
| @@ -19,7 +19,7 @@ type traceWrapper struct { | ||||
| 	client.Client | ||||
|  | ||||
| 	name  string | ||||
| 	trace trace.Trace | ||||
| 	trace trace.Tracer | ||||
| } | ||||
|  | ||||
| var ( | ||||
| @@ -97,7 +97,7 @@ func HandlerStats(stats stats.Stats) server.HandlerWrapper { | ||||
| } | ||||
|  | ||||
| // TraceCall is a call tracing wrapper | ||||
| func TraceCall(name string, t trace.Trace, c client.Client) client.Client { | ||||
| func TraceCall(name string, t trace.Tracer, c client.Client) client.Client { | ||||
| 	return &traceWrapper{ | ||||
| 		name:   name, | ||||
| 		trace:  t, | ||||
| @@ -106,7 +106,7 @@ func TraceCall(name string, t trace.Trace, c client.Client) client.Client { | ||||
| } | ||||
|  | ||||
| // TraceHandler wraps a server handler to perform tracing | ||||
| func TraceHandler(t trace.Trace) server.HandlerWrapper { | ||||
| func TraceHandler(t trace.Tracer) server.HandlerWrapper { | ||||
| 	// return a handler wrapper | ||||
| 	return func(h server.HandlerFunc) server.HandlerFunc { | ||||
| 		// return a function that returns a function | ||||
|   | ||||
		Reference in New Issue
	
	Block a user