mirror of
				https://github.com/go-micro/go-micro.git
				synced 2025-10-30 23:27:41 +02:00 
			
		
		
		
	Add monitor/debug packages
This commit is contained in:
		
							
								
								
									
										41
									
								
								debug/handler/debug.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								debug/handler/debug.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package handler | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"runtime" | ||||
| 	"time" | ||||
|  | ||||
| 	proto "github.com/micro/go-micro/debug/proto" | ||||
| ) | ||||
|  | ||||
| type Debug struct { | ||||
| 	proto.DebugHandler | ||||
| 	started int64 | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	DefaultHandler = newDebug() | ||||
| ) | ||||
|  | ||||
| func newDebug() *Debug { | ||||
| 	return &Debug{ | ||||
| 		started: time.Now().Unix(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (d *Debug) Health(ctx context.Context, req *proto.HealthRequest, rsp *proto.HealthResponse) error { | ||||
| 	rsp.Status = "ok" | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.StatsResponse) error { | ||||
| 	var mstat runtime.MemStats | ||||
| 	runtime.ReadMemStats(&mstat) | ||||
|  | ||||
| 	rsp.Started = uint64(d.started) | ||||
| 	rsp.Uptime = uint64(time.Now().Unix() - d.started) | ||||
| 	rsp.Memory = mstat.Alloc | ||||
| 	rsp.Gc = mstat.PauseTotalNs | ||||
| 	rsp.Threads = uint64(runtime.NumGoroutine()) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										108
									
								
								debug/proto/debug.micro.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								debug/proto/debug.micro.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| // Code generated by protoc-gen-micro. DO NOT EDIT. | ||||
| // source: micro/go-micro/debug/proto/debug.proto | ||||
|  | ||||
| package debug | ||||
|  | ||||
| import ( | ||||
| 	fmt "fmt" | ||||
| 	proto "github.com/golang/protobuf/proto" | ||||
| 	math "math" | ||||
| ) | ||||
|  | ||||
| import ( | ||||
| 	context "context" | ||||
| 	client "github.com/micro/go-micro/client" | ||||
| 	server "github.com/micro/go-micro/server" | ||||
| ) | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| // A compilation error at this line likely means your copy of the | ||||
| // proto package needs to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ context.Context | ||||
| var _ client.Option | ||||
| var _ server.Option | ||||
|  | ||||
| // Client API for Debug service | ||||
|  | ||||
| type DebugService interface { | ||||
| 	Health(ctx context.Context, in *HealthRequest, opts ...client.CallOption) (*HealthResponse, error) | ||||
| 	Stats(ctx context.Context, in *StatsRequest, opts ...client.CallOption) (*StatsResponse, error) | ||||
| } | ||||
|  | ||||
| type debugService struct { | ||||
| 	c    client.Client | ||||
| 	name string | ||||
| } | ||||
|  | ||||
| func NewDebugService(name string, c client.Client) DebugService { | ||||
| 	if c == nil { | ||||
| 		c = client.NewClient() | ||||
| 	} | ||||
| 	if len(name) == 0 { | ||||
| 		name = "debug" | ||||
| 	} | ||||
| 	return &debugService{ | ||||
| 		c:    c, | ||||
| 		name: name, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *debugService) Health(ctx context.Context, in *HealthRequest, opts ...client.CallOption) (*HealthResponse, error) { | ||||
| 	req := c.c.NewRequest(c.name, "Debug.Health", in) | ||||
| 	out := new(HealthResponse) | ||||
| 	err := c.c.Call(ctx, req, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *debugService) Stats(ctx context.Context, in *StatsRequest, opts ...client.CallOption) (*StatsResponse, error) { | ||||
| 	req := c.c.NewRequest(c.name, "Debug.Stats", in) | ||||
| 	out := new(StatsResponse) | ||||
| 	err := c.c.Call(ctx, req, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Server API for Debug service | ||||
|  | ||||
| type DebugHandler interface { | ||||
| 	Health(context.Context, *HealthRequest, *HealthResponse) error | ||||
| 	Stats(context.Context, *StatsRequest, *StatsResponse) error | ||||
| } | ||||
|  | ||||
| func RegisterDebugHandler(s server.Server, hdlr DebugHandler, opts ...server.HandlerOption) error { | ||||
| 	type debug interface { | ||||
| 		Health(ctx context.Context, in *HealthRequest, out *HealthResponse) error | ||||
| 		Stats(ctx context.Context, in *StatsRequest, out *StatsResponse) error | ||||
| 	} | ||||
| 	type Debug struct { | ||||
| 		debug | ||||
| 	} | ||||
| 	h := &debugHandler{hdlr} | ||||
| 	return s.Handle(s.NewHandler(&Debug{h}, opts...)) | ||||
| } | ||||
|  | ||||
| type debugHandler struct { | ||||
| 	DebugHandler | ||||
| } | ||||
|  | ||||
| func (h *debugHandler) Health(ctx context.Context, in *HealthRequest, out *HealthResponse) error { | ||||
| 	return h.DebugHandler.Health(ctx, in, out) | ||||
| } | ||||
|  | ||||
| func (h *debugHandler) Stats(ctx context.Context, in *StatsRequest, out *StatsResponse) error { | ||||
| 	return h.DebugHandler.Stats(ctx, in, out) | ||||
| } | ||||
							
								
								
									
										336
									
								
								debug/proto/debug.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										336
									
								
								debug/proto/debug.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,336 @@ | ||||
| // Code generated by protoc-gen-go. DO NOT EDIT. | ||||
| // source: micro/go-micro/debug/proto/debug.proto | ||||
|  | ||||
| package debug | ||||
|  | ||||
| import ( | ||||
| 	context "context" | ||||
| 	fmt "fmt" | ||||
| 	proto "github.com/golang/protobuf/proto" | ||||
| 	grpc "google.golang.org/grpc" | ||||
| 	math "math" | ||||
| ) | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| // A compilation error at this line likely means your copy of the | ||||
| // proto package needs to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package | ||||
|  | ||||
| type HealthRequest struct { | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *HealthRequest) Reset()         { *m = HealthRequest{} } | ||||
| func (m *HealthRequest) String() string { return proto.CompactTextString(m) } | ||||
| func (*HealthRequest) ProtoMessage()    {} | ||||
| func (*HealthRequest) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_f25415e61bccfa1f, []int{0} | ||||
| } | ||||
|  | ||||
| func (m *HealthRequest) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_HealthRequest.Unmarshal(m, b) | ||||
| } | ||||
| func (m *HealthRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_HealthRequest.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *HealthRequest) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_HealthRequest.Merge(m, src) | ||||
| } | ||||
| func (m *HealthRequest) XXX_Size() int { | ||||
| 	return xxx_messageInfo_HealthRequest.Size(m) | ||||
| } | ||||
| func (m *HealthRequest) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_HealthRequest.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_HealthRequest proto.InternalMessageInfo | ||||
|  | ||||
| type HealthResponse struct { | ||||
| 	// default: ok | ||||
| 	Status               string   `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *HealthResponse) Reset()         { *m = HealthResponse{} } | ||||
| func (m *HealthResponse) String() string { return proto.CompactTextString(m) } | ||||
| func (*HealthResponse) ProtoMessage()    {} | ||||
| func (*HealthResponse) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_f25415e61bccfa1f, []int{1} | ||||
| } | ||||
|  | ||||
| func (m *HealthResponse) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_HealthResponse.Unmarshal(m, b) | ||||
| } | ||||
| func (m *HealthResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_HealthResponse.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *HealthResponse) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_HealthResponse.Merge(m, src) | ||||
| } | ||||
| func (m *HealthResponse) XXX_Size() int { | ||||
| 	return xxx_messageInfo_HealthResponse.Size(m) | ||||
| } | ||||
| func (m *HealthResponse) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_HealthResponse.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_HealthResponse proto.InternalMessageInfo | ||||
|  | ||||
| func (m *HealthResponse) GetStatus() string { | ||||
| 	if m != nil { | ||||
| 		return m.Status | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type StatsRequest struct { | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *StatsRequest) Reset()         { *m = StatsRequest{} } | ||||
| func (m *StatsRequest) String() string { return proto.CompactTextString(m) } | ||||
| func (*StatsRequest) ProtoMessage()    {} | ||||
| func (*StatsRequest) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_f25415e61bccfa1f, []int{2} | ||||
| } | ||||
|  | ||||
| func (m *StatsRequest) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_StatsRequest.Unmarshal(m, b) | ||||
| } | ||||
| func (m *StatsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_StatsRequest.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *StatsRequest) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_StatsRequest.Merge(m, src) | ||||
| } | ||||
| func (m *StatsRequest) XXX_Size() int { | ||||
| 	return xxx_messageInfo_StatsRequest.Size(m) | ||||
| } | ||||
| func (m *StatsRequest) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_StatsRequest.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_StatsRequest proto.InternalMessageInfo | ||||
|  | ||||
| type StatsResponse struct { | ||||
| 	// unix timestamp | ||||
| 	Started uint64 `protobuf:"varint,1,opt,name=started,proto3" json:"started,omitempty"` | ||||
| 	// in seconds | ||||
| 	Uptime uint64 `protobuf:"varint,2,opt,name=uptime,proto3" json:"uptime,omitempty"` | ||||
| 	// in bytes | ||||
| 	Memory uint64 `protobuf:"varint,3,opt,name=memory,proto3" json:"memory,omitempty"` | ||||
| 	// num threads | ||||
| 	Threads uint64 `protobuf:"varint,4,opt,name=threads,proto3" json:"threads,omitempty"` | ||||
| 	// total gc in nanoseconds | ||||
| 	Gc                   uint64   `protobuf:"varint,5,opt,name=gc,proto3" json:"gc,omitempty"` | ||||
| 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||
| 	XXX_unrecognized     []byte   `json:"-"` | ||||
| 	XXX_sizecache        int32    `json:"-"` | ||||
| } | ||||
|  | ||||
| func (m *StatsResponse) Reset()         { *m = StatsResponse{} } | ||||
| func (m *StatsResponse) String() string { return proto.CompactTextString(m) } | ||||
| func (*StatsResponse) ProtoMessage()    {} | ||||
| func (*StatsResponse) Descriptor() ([]byte, []int) { | ||||
| 	return fileDescriptor_f25415e61bccfa1f, []int{3} | ||||
| } | ||||
|  | ||||
| func (m *StatsResponse) XXX_Unmarshal(b []byte) error { | ||||
| 	return xxx_messageInfo_StatsResponse.Unmarshal(m, b) | ||||
| } | ||||
| func (m *StatsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||
| 	return xxx_messageInfo_StatsResponse.Marshal(b, m, deterministic) | ||||
| } | ||||
| func (m *StatsResponse) XXX_Merge(src proto.Message) { | ||||
| 	xxx_messageInfo_StatsResponse.Merge(m, src) | ||||
| } | ||||
| func (m *StatsResponse) XXX_Size() int { | ||||
| 	return xxx_messageInfo_StatsResponse.Size(m) | ||||
| } | ||||
| func (m *StatsResponse) XXX_DiscardUnknown() { | ||||
| 	xxx_messageInfo_StatsResponse.DiscardUnknown(m) | ||||
| } | ||||
|  | ||||
| var xxx_messageInfo_StatsResponse proto.InternalMessageInfo | ||||
|  | ||||
| func (m *StatsResponse) GetStarted() uint64 { | ||||
| 	if m != nil { | ||||
| 		return m.Started | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *StatsResponse) GetUptime() uint64 { | ||||
| 	if m != nil { | ||||
| 		return m.Uptime | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *StatsResponse) GetMemory() uint64 { | ||||
| 	if m != nil { | ||||
| 		return m.Memory | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *StatsResponse) GetThreads() uint64 { | ||||
| 	if m != nil { | ||||
| 		return m.Threads | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (m *StatsResponse) GetGc() uint64 { | ||||
| 	if m != nil { | ||||
| 		return m.Gc | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterType((*HealthRequest)(nil), "HealthRequest") | ||||
| 	proto.RegisterType((*HealthResponse)(nil), "HealthResponse") | ||||
| 	proto.RegisterType((*StatsRequest)(nil), "StatsRequest") | ||||
| 	proto.RegisterType((*StatsResponse)(nil), "StatsResponse") | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterFile("micro/go-micro/debug/proto/debug.proto", fileDescriptor_f25415e61bccfa1f) | ||||
| } | ||||
|  | ||||
| var fileDescriptor_f25415e61bccfa1f = []byte{ | ||||
| 	// 230 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x90, 0x41, 0x4b, 0xc4, 0x30, | ||||
| 	0x10, 0x85, 0xb7, 0x75, 0x5b, 0x71, 0xb0, 0x59, 0xc8, 0x41, 0xc2, 0x9e, 0x24, 0x07, 0x29, 0x88, | ||||
| 	0x59, 0xd0, 0xbf, 0xe0, 0xc1, 0x73, 0xbd, 0x0b, 0xd9, 0x76, 0xe8, 0x16, 0xac, 0xa9, 0x99, 0xe9, | ||||
| 	0xc1, 0xb3, 0x7f, 0x5c, 0x9a, 0xa4, 0x60, 0x6f, 0xef, 0xbd, 0xf0, 0x1e, 0xf9, 0x06, 0x1e, 0xc6, | ||||
| 	0xa1, 0xf5, 0xee, 0xd4, 0xbb, 0xa7, 0x28, 0x3a, 0x3c, 0xcf, 0xfd, 0x69, 0xf2, 0x8e, 0x93, 0x36, | ||||
| 	0x41, 0xeb, 0x03, 0x54, 0x6f, 0x68, 0x3f, 0xf9, 0xd2, 0xe0, 0xf7, 0x8c, 0xc4, 0xba, 0x06, 0xb1, | ||||
| 	0x06, 0x34, 0xb9, 0x2f, 0x42, 0x79, 0x07, 0x25, 0xb1, 0xe5, 0x99, 0x54, 0x76, 0x9f, 0xd5, 0x37, | ||||
| 	0x4d, 0x72, 0x5a, 0xc0, 0xed, 0x3b, 0x5b, 0xa6, 0xb5, 0xf9, 0x9b, 0x41, 0x95, 0x82, 0xd4, 0x54, | ||||
| 	0x70, 0x4d, 0x6c, 0x3d, 0x63, 0x17, 0xaa, 0xfb, 0x66, 0xb5, 0xcb, 0xe6, 0x3c, 0xf1, 0x30, 0xa2, | ||||
| 	0xca, 0xc3, 0x43, 0x72, 0x4b, 0x3e, 0xe2, 0xe8, 0xfc, 0x8f, 0xba, 0x8a, 0x79, 0x74, 0xcb, 0x12, | ||||
| 	0x5f, 0x3c, 0xda, 0x8e, 0xd4, 0x3e, 0x2e, 0x25, 0x2b, 0x05, 0xe4, 0x7d, 0xab, 0x8a, 0x10, 0xe6, | ||||
| 	0x7d, 0xfb, 0xfc, 0x01, 0xc5, 0xeb, 0xc2, 0x27, 0x1f, 0xa1, 0x8c, 0x20, 0x52, 0x98, 0x0d, 0xe2, | ||||
| 	0xf1, 0x60, 0xb6, 0x84, 0x7a, 0x27, 0x6b, 0x28, 0xc2, 0xd7, 0x65, 0x65, 0xfe, 0x33, 0x1d, 0x85, | ||||
| 	0xd9, 0x10, 0xe9, 0xdd, 0xb9, 0x0c, 0x77, 0x7b, 0xf9, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xb9, | ||||
| 	0x5f, 0xf7, 0x61, 0x01, 0x00, 0x00, | ||||
| } | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ context.Context | ||||
| var _ grpc.ClientConn | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the grpc package it is being compiled against. | ||||
| const _ = grpc.SupportPackageIsVersion4 | ||||
|  | ||||
| // DebugClient is the client API for Debug service. | ||||
| // | ||||
| // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. | ||||
| type DebugClient interface { | ||||
| 	Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) | ||||
| 	Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error) | ||||
| } | ||||
|  | ||||
| type debugClient struct { | ||||
| 	cc *grpc.ClientConn | ||||
| } | ||||
|  | ||||
| func NewDebugClient(cc *grpc.ClientConn) DebugClient { | ||||
| 	return &debugClient{cc} | ||||
| } | ||||
|  | ||||
| func (c *debugClient) Health(ctx context.Context, in *HealthRequest, opts ...grpc.CallOption) (*HealthResponse, error) { | ||||
| 	out := new(HealthResponse) | ||||
| 	err := c.cc.Invoke(ctx, "/Debug/Health", in, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *debugClient) Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsResponse, error) { | ||||
| 	out := new(StatsResponse) | ||||
| 	err := c.cc.Invoke(ctx, "/Debug/Stats", in, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // DebugServer is the server API for Debug service. | ||||
| type DebugServer interface { | ||||
| 	Health(context.Context, *HealthRequest) (*HealthResponse, error) | ||||
| 	Stats(context.Context, *StatsRequest) (*StatsResponse, error) | ||||
| } | ||||
|  | ||||
| func RegisterDebugServer(s *grpc.Server, srv DebugServer) { | ||||
| 	s.RegisterService(&_Debug_serviceDesc, srv) | ||||
| } | ||||
|  | ||||
| func _Debug_Health_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(HealthRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if interceptor == nil { | ||||
| 		return srv.(DebugServer).Health(ctx, in) | ||||
| 	} | ||||
| 	info := &grpc.UnaryServerInfo{ | ||||
| 		Server:     srv, | ||||
| 		FullMethod: "/Debug/Health", | ||||
| 	} | ||||
| 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||
| 		return srv.(DebugServer).Health(ctx, req.(*HealthRequest)) | ||||
| 	} | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| func _Debug_Stats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(StatsRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if interceptor == nil { | ||||
| 		return srv.(DebugServer).Stats(ctx, in) | ||||
| 	} | ||||
| 	info := &grpc.UnaryServerInfo{ | ||||
| 		Server:     srv, | ||||
| 		FullMethod: "/Debug/Stats", | ||||
| 	} | ||||
| 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||
| 		return srv.(DebugServer).Stats(ctx, req.(*StatsRequest)) | ||||
| 	} | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| var _Debug_serviceDesc = grpc.ServiceDesc{ | ||||
| 	ServiceName: "Debug", | ||||
| 	HandlerType: (*DebugServer)(nil), | ||||
| 	Methods: []grpc.MethodDesc{ | ||||
| 		{ | ||||
| 			MethodName: "Health", | ||||
| 			Handler:    _Debug_Health_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "Stats", | ||||
| 			Handler:    _Debug_Stats_Handler, | ||||
| 		}, | ||||
| 	}, | ||||
| 	Streams:  []grpc.StreamDesc{}, | ||||
| 	Metadata: "micro/go-micro/debug/proto/debug.proto", | ||||
| } | ||||
| @@ -1,13 +1,9 @@ | ||||
| syntax = "proto3"; | ||||
| 
 | ||||
| // This is commented out due to import cycles. | ||||
| // But its what we expect the RPC service to  | ||||
| // return. | ||||
| // | ||||
| // service Debug { | ||||
| // 	rpc Health(HealthRequest) returns (HealthResponse) {} | ||||
| // 	rpc Stats(StatsRequest) returns (StatsResponse) {} | ||||
| // } | ||||
| service Debug { | ||||
|  	rpc Health(HealthRequest) returns (HealthResponse) {} | ||||
|  	rpc Stats(StatsRequest) returns (StatsResponse) {} | ||||
| } | ||||
| 
 | ||||
| message HealthRequest { | ||||
| } | ||||
| @@ -5,8 +5,8 @@ import ( | ||||
| 	"sync" | ||||
| 	"testing" | ||||
|  | ||||
| 	proto "github.com/micro/go-micro/debug/proto" | ||||
| 	"github.com/micro/go-micro/registry/memory" | ||||
| 	proto "github.com/micro/go-micro/server/debug/proto" | ||||
| ) | ||||
|  | ||||
| func TestFunction(t *testing.T) { | ||||
|   | ||||
							
								
								
									
										213
									
								
								monitor/default.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								monitor/default.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,213 @@ | ||||
| package monitor | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	pb "github.com/micro/go-micro/debug/proto" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/registry/cache" | ||||
| ) | ||||
|  | ||||
| type monitor struct { | ||||
| 	options Options | ||||
|  | ||||
| 	exit     chan bool | ||||
| 	registry cache.Cache | ||||
| 	client   client.Client | ||||
|  | ||||
| 	sync.RWMutex | ||||
| 	services map[string]*Status | ||||
| } | ||||
|  | ||||
| // check provides binary running/failed status. | ||||
| // In the event Debug.Health cannot be called on a service we reap the node. | ||||
| func (m *monitor) check(service string) (*Status, error) { | ||||
| 	services, err := m.registry.GetService(service) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// create debug client | ||||
| 	debug := pb.NewDebugService(service, m.client) | ||||
|  | ||||
| 	var status *Status | ||||
| 	var gerr error | ||||
|  | ||||
| 	// iterate through multiple versions of a service | ||||
| 	for _, service := range services { | ||||
| 		for _, node := range service.Nodes { | ||||
| 			rsp, err := debug.Health( | ||||
| 				context.Background(), | ||||
| 				// empty health request | ||||
| 				&pb.HealthRequest{}, | ||||
| 				// call this specific node | ||||
| 				client.WithAddress(node.Address), | ||||
| 				// retry in the event of failure | ||||
| 				client.WithRetries(3), | ||||
| 			) | ||||
| 			if err != nil { | ||||
| 				// reap the dead node | ||||
| 				m.registry.Deregister(®istry.Service{ | ||||
| 					Name:    service.Name, | ||||
| 					Version: service.Version, | ||||
| 					Nodes:   []*registry.Node{node}, | ||||
| 				}) | ||||
|  | ||||
| 				// save the error | ||||
| 				gerr = err | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			// expecting ok response status | ||||
| 			if rsp.Status != "ok" { | ||||
| 				gerr = errors.New(rsp.Status) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			// no error set status | ||||
| 			status = &Status{ | ||||
| 				Code: StatusRunning, | ||||
| 				Info: "running", | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// if we got the success case return it | ||||
| 	if status != nil { | ||||
| 		return status, nil | ||||
| 	} | ||||
|  | ||||
| 	// if gerr is not nil return it | ||||
| 	if gerr != nil { | ||||
| 		return &Status{ | ||||
| 			Code:  StatusFailed, | ||||
| 			Info:  "not running", | ||||
| 			Error: gerr.Error(), | ||||
| 		}, nil | ||||
| 	} | ||||
|  | ||||
| 	// otherwise unknown status | ||||
| 	return &Status{ | ||||
| 		Code: StatusUnknown, | ||||
| 		Info: "unknown status", | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (m *monitor) Status(service string) (Status, error) { | ||||
| 	m.RLock() | ||||
| 	defer m.RUnlock() | ||||
| 	if status, ok := m.services[service]; ok { | ||||
| 		return *status, nil | ||||
| 	} | ||||
| 	return Status{}, ErrNotWatching | ||||
| } | ||||
|  | ||||
| func (m *monitor) Watch(service string) error { | ||||
| 	m.Lock() | ||||
| 	defer m.Unlock() | ||||
|  | ||||
| 	// check if we're watching | ||||
| 	if _, ok := m.services[service]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// get the status | ||||
| 	status, err := m.check(service) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// set the status | ||||
| 	m.services[service] = status | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *monitor) Stop() error { | ||||
| 	m.Lock() | ||||
| 	defer m.RUnlock() | ||||
|  | ||||
| 	select { | ||||
| 	case <-m.exit: | ||||
| 		return nil | ||||
| 	default: | ||||
| 		close(m.exit) | ||||
| 		for s, _ := range m.services { | ||||
| 			delete(m.services, s) | ||||
| 		} | ||||
| 		m.registry.Stop() | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *monitor) run() { | ||||
| 	// check the status every tick | ||||
| 	t := time.NewTicker(time.Minute) | ||||
| 	defer t.Stop() | ||||
|  | ||||
| 	check := make(chan string) | ||||
|  | ||||
| 	for { | ||||
| 		select { | ||||
| 		case <-m.exit: | ||||
| 			return | ||||
| 		case service := <-check: | ||||
| 			// check the status | ||||
| 			status, err := m.check(service) | ||||
| 			if err != nil { | ||||
| 				status = &Status{ | ||||
| 					Code: StatusUnknown, | ||||
| 					Info: "unknown status", | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// save the status | ||||
| 			m.Lock() | ||||
| 			m.services[service] = status | ||||
| 			m.Unlock() | ||||
| 		case <-t.C: | ||||
| 			// create a list of services | ||||
| 			var services []string | ||||
| 			m.RLock() | ||||
| 			for service, _ := range m.services { | ||||
| 				services = append(services, service) | ||||
| 			} | ||||
| 			m.RUnlock() | ||||
|  | ||||
| 			// check the status of all watched services | ||||
| 			for _, service := range services { | ||||
| 				select { | ||||
| 				case <-m.exit: | ||||
| 					return | ||||
| 				case check <- service: | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func newMonitor(opts ...Option) Monitor { | ||||
| 	options := Options{ | ||||
| 		Client:   client.DefaultClient, | ||||
| 		Registry: registry.DefaultRegistry, | ||||
| 	} | ||||
|  | ||||
| 	for _, o := range opts { | ||||
| 		o(&options) | ||||
| 	} | ||||
|  | ||||
| 	m := &monitor{ | ||||
| 		options:  options, | ||||
| 		client:   options.Client, | ||||
| 		registry: cache.New(options.Registry), | ||||
| 		services: make(map[string]*Status), | ||||
| 	} | ||||
|  | ||||
| 	go m.run() | ||||
| 	return m | ||||
| } | ||||
							
								
								
									
										19
									
								
								monitor/default_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								monitor/default_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| package monitor | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestMonitor(t *testing.T) { | ||||
| 	// create new monitor | ||||
| 	m := NewMonitor() | ||||
|  | ||||
| 	services := []string{"foo", "bar", "baz"} | ||||
|  | ||||
| 	for _, service := range services { | ||||
| 		_, err := m.Status(service) | ||||
| 		if err != nil { | ||||
| 			t.Fatal("expected status error for unknown service") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										39
									
								
								monitor/monitor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								monitor/monitor.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| // Package monitor monitors service health | ||||
| package monitor | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	StatusUnknown StatusCode = iota | ||||
| 	StatusRunning | ||||
| 	StatusFailed | ||||
| ) | ||||
|  | ||||
| type StatusCode int | ||||
|  | ||||
| // Monitor monitors a service and reaps dead instances | ||||
| type Monitor interface { | ||||
| 	// Status of the service | ||||
| 	Status(service string) (Status, error) | ||||
| 	// Watch starts watching the service | ||||
| 	Watch(service string) error | ||||
| 	// Stop monitoring | ||||
| 	Stop() error | ||||
| } | ||||
|  | ||||
| type Status struct { | ||||
| 	Code  StatusCode | ||||
| 	Info  string | ||||
| 	Error string | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	ErrNotWatching = errors.New("not watching") | ||||
| ) | ||||
|  | ||||
| // NewMonitor returns a new monitor | ||||
| func NewMonitor(opts ...Option) Monitor { | ||||
| 	return newMonitor(opts...) | ||||
| } | ||||
							
								
								
									
										25
									
								
								monitor/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								monitor/options.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package monitor | ||||
|  | ||||
| import ( | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| ) | ||||
|  | ||||
| type Options struct { | ||||
| 	Client   client.Client | ||||
| 	Registry registry.Registry | ||||
| } | ||||
|  | ||||
| type Option func(*Options) | ||||
|  | ||||
| func Client(c client.Client) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Client = c | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Registry(r registry.Registry) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Registry = r | ||||
| 	} | ||||
| } | ||||
| @@ -1,9 +0,0 @@ | ||||
| package server | ||||
|  | ||||
| import ( | ||||
| 	"github.com/micro/go-micro/server/debug" | ||||
| ) | ||||
|  | ||||
| func registerDebugHandler(s Server) { | ||||
| 	s.Handle(s.NewHandler(&debug.Debug{s.Options().DebugHandler}, InternalHandler(true))) | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| package debug | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"runtime" | ||||
| 	"time" | ||||
|  | ||||
| 	proto "github.com/micro/go-micro/server/debug/proto" | ||||
| ) | ||||
|  | ||||
| // The debug handler represents an internal server handler | ||||
| // used to determine health, status and env info about | ||||
| // a service node. It's akin to Google's /statusz, /healthz, | ||||
| // and /varz | ||||
| type Handler interface { | ||||
| 	Health(ctx context.Context, req *proto.HealthRequest, rsp *proto.HealthResponse) error | ||||
| 	Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.StatsResponse) error | ||||
| } | ||||
|  | ||||
| // Our own internal handler | ||||
| type debug struct { | ||||
| 	started int64 | ||||
| } | ||||
|  | ||||
| // We use this to wrap any debug handlers so we preserve the signature Debug.{Method} | ||||
| type Debug struct { | ||||
| 	Handler | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	DefaultHandler Handler = newDebug() | ||||
| ) | ||||
|  | ||||
| func newDebug() *debug { | ||||
| 	return &debug{ | ||||
| 		started: time.Now().Unix(), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (d *debug) Health(ctx context.Context, req *proto.HealthRequest, rsp *proto.HealthResponse) error { | ||||
| 	rsp.Status = "ok" | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (d *debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.StatsResponse) error { | ||||
| 	var mstat runtime.MemStats | ||||
| 	runtime.ReadMemStats(&mstat) | ||||
|  | ||||
| 	rsp.Started = uint64(d.started) | ||||
| 	rsp.Uptime = uint64(time.Now().Unix() - d.started) | ||||
| 	rsp.Memory = mstat.Alloc | ||||
| 	rsp.Gc = mstat.PauseTotalNs | ||||
| 	rsp.Threads = uint64(runtime.NumGoroutine()) | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,100 +0,0 @@ | ||||
| // Code generated by protoc-gen-go. | ||||
| // source: github.com/micro/go-micro/server/debug/proto/debug.proto | ||||
| // DO NOT EDIT! | ||||
|  | ||||
| /* | ||||
| Package debug is a generated protocol buffer package. | ||||
|  | ||||
| It is generated from these files: | ||||
| 	github.com/micro/go-micro/server/debug/proto/debug.proto | ||||
|  | ||||
| It has these top-level messages: | ||||
| 	HealthRequest | ||||
| 	HealthResponse | ||||
| 	StatsRequest | ||||
| 	StatsResponse | ||||
| */ | ||||
| package debug | ||||
|  | ||||
| import proto "github.com/golang/protobuf/proto" | ||||
| import fmt "fmt" | ||||
| import math "math" | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| // A compilation error at this line likely means your copy of the | ||||
| // proto package needs to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package | ||||
|  | ||||
| type HealthRequest struct { | ||||
| } | ||||
|  | ||||
| func (m *HealthRequest) Reset()                    { *m = HealthRequest{} } | ||||
| func (m *HealthRequest) String() string            { return proto.CompactTextString(m) } | ||||
| func (*HealthRequest) ProtoMessage()               {} | ||||
| func (*HealthRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } | ||||
|  | ||||
| type HealthResponse struct { | ||||
| 	// default: ok | ||||
| 	Status string `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"` | ||||
| } | ||||
|  | ||||
| func (m *HealthResponse) Reset()                    { *m = HealthResponse{} } | ||||
| func (m *HealthResponse) String() string            { return proto.CompactTextString(m) } | ||||
| func (*HealthResponse) ProtoMessage()               {} | ||||
| func (*HealthResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } | ||||
|  | ||||
| type StatsRequest struct { | ||||
| } | ||||
|  | ||||
| func (m *StatsRequest) Reset()                    { *m = StatsRequest{} } | ||||
| func (m *StatsRequest) String() string            { return proto.CompactTextString(m) } | ||||
| func (*StatsRequest) ProtoMessage()               {} | ||||
| func (*StatsRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } | ||||
|  | ||||
| type StatsResponse struct { | ||||
| 	// unix timestamp | ||||
| 	Started uint64 `protobuf:"varint,1,opt,name=started" json:"started,omitempty"` | ||||
| 	// in seconds | ||||
| 	Uptime uint64 `protobuf:"varint,2,opt,name=uptime" json:"uptime,omitempty"` | ||||
| 	// in bytes | ||||
| 	Memory uint64 `protobuf:"varint,3,opt,name=memory" json:"memory,omitempty"` | ||||
| 	// num threads | ||||
| 	Threads uint64 `protobuf:"varint,4,opt,name=threads" json:"threads,omitempty"` | ||||
| 	// in nanoseconds | ||||
| 	Gc uint64 `protobuf:"varint,5,opt,name=gc" json:"gc,omitempty"` | ||||
| } | ||||
|  | ||||
| func (m *StatsResponse) Reset()                    { *m = StatsResponse{} } | ||||
| func (m *StatsResponse) String() string            { return proto.CompactTextString(m) } | ||||
| func (*StatsResponse) ProtoMessage()               {} | ||||
| func (*StatsResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterType((*HealthRequest)(nil), "HealthRequest") | ||||
| 	proto.RegisterType((*HealthResponse)(nil), "HealthResponse") | ||||
| 	proto.RegisterType((*StatsRequest)(nil), "StatsRequest") | ||||
| 	proto.RegisterType((*StatsResponse)(nil), "StatsResponse") | ||||
| } | ||||
|  | ||||
| var fileDescriptor0 = []byte{ | ||||
| 	// 201 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x34, 0x8f, 0xbd, 0x6e, 0x83, 0x30, | ||||
| 	0x14, 0x85, 0x05, 0xa5, 0x54, 0xbd, 0x2a, 0x54, 0x62, 0xa8, 0x3c, 0x56, 0x4c, 0x2c, 0xc5, 0x43, | ||||
| 	0x97, 0x3e, 0x42, 0x67, 0xf2, 0x04, 0xfc, 0x5c, 0x19, 0xa4, 0x38, 0x26, 0xbe, 0xd7, 0x91, 0x32, | ||||
| 	0xe7, 0xc5, 0x03, 0xb6, 0xd9, 0xce, 0xf7, 0xd9, 0xe7, 0x48, 0x17, 0xfe, 0xd4, 0xc2, 0xb3, 0x1b, | ||||
| 	0xda, 0xd1, 0x68, 0xa9, 0x97, 0xd1, 0x1a, 0xa9, 0xcc, 0x4f, 0x08, 0x84, 0xf6, 0x86, 0x56, 0x4e, | ||||
| 	0x38, 0x38, 0x25, 0x57, 0x6b, 0xd8, 0x84, 0xdc, 0xfa, 0x5c, 0x7f, 0x42, 0xf1, 0x8f, 0xfd, 0x99, | ||||
| 	0xe7, 0x0e, 0xaf, 0x0e, 0x89, 0xeb, 0x06, 0xca, 0x43, 0xd0, 0x6a, 0x2e, 0x84, 0xd5, 0x17, 0xe4, | ||||
| 	0xc4, 0x3d, 0x3b, 0x12, 0xc9, 0x77, 0xd2, 0xbc, 0x77, 0x91, 0xea, 0x12, 0x3e, 0x4e, 0x5b, 0xa2, | ||||
| 	0xa3, 0xf9, 0x48, 0xa0, 0x88, 0x22, 0x36, 0x05, 0xbc, 0x6d, 0x7f, 0x2d, 0xe3, 0xe4, 0xab, 0x59, | ||||
| 	0x77, 0xe0, 0xbe, 0xe9, 0x56, 0x5e, 0x34, 0x8a, 0xd4, 0x3f, 0x44, 0xda, 0xbd, 0x46, 0x6d, 0xec, | ||||
| 	0x5d, 0xbc, 0x04, 0x1f, 0x68, 0x5f, 0xe2, 0xd9, 0x62, 0x3f, 0x91, 0xc8, 0xc2, 0x52, 0xc4, 0xaa, | ||||
| 	0x84, 0x54, 0x8d, 0xe2, 0xd5, 0xcb, 0x2d, 0x0d, 0xb9, 0xbf, 0xeb, 0xf7, 0x19, 0x00, 0x00, 0xff, | ||||
| 	0xff, 0xc6, 0x75, 0x51, 0x35, 0x13, 0x01, 0x00, 0x00, | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| package grpc | ||||
|  | ||||
| import ( | ||||
| 	"github.com/micro/go-micro/server" | ||||
| 	"github.com/micro/go-micro/server/debug" | ||||
| ) | ||||
|  | ||||
| func registerDebugHandler(s server.Server) { | ||||
| 	s.Handle(s.NewHandler(&debug.Debug{s.Options().DebugHandler}, server.InternalHandler(true))) | ||||
| } | ||||
| @@ -700,7 +700,6 @@ func (g *grpcServer) Deregister() error { | ||||
| } | ||||
|  | ||||
| func (g *grpcServer) Start() error { | ||||
| 	registerDebugHandler(g) | ||||
| 	config := g.opts | ||||
|  | ||||
| 	// micro: config.Transport.Listen(config.Address) | ||||
|   | ||||
| @@ -8,7 +8,6 @@ import ( | ||||
| 	"github.com/micro/go-micro/codec" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| 	"github.com/micro/go-micro/server/debug" | ||||
| 	"github.com/micro/go-micro/transport" | ||||
| 	"google.golang.org/grpc" | ||||
| 	"google.golang.org/grpc/encoding" | ||||
| @@ -89,10 +88,6 @@ func newOptions(opt ...server.Option) server.Options { | ||||
| 		opts.Transport = transport.DefaultTransport | ||||
| 	} | ||||
|  | ||||
| 	if opts.DebugHandler == nil { | ||||
| 		opts.DebugHandler = debug.DefaultHandler | ||||
| 	} | ||||
|  | ||||
| 	if len(opts.Address) == 0 { | ||||
| 		opts.Address = server.DefaultAddress | ||||
| 	} | ||||
|   | ||||
| @@ -8,7 +8,6 @@ import ( | ||||
| 	"github.com/micro/go-micro/broker" | ||||
| 	"github.com/micro/go-micro/codec" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/server/debug" | ||||
| 	"github.com/micro/go-micro/transport" | ||||
| ) | ||||
|  | ||||
| @@ -36,9 +35,6 @@ type Options struct { | ||||
| 	// The router for requests | ||||
| 	Router Router | ||||
|  | ||||
| 	// Debug Handler which can be set by a user | ||||
| 	DebugHandler debug.Handler | ||||
|  | ||||
| 	// Other options for implementations of the interface | ||||
| 	// can be stored in a context | ||||
| 	Context context.Context | ||||
| @@ -66,10 +62,6 @@ func newOptions(opt ...Option) Options { | ||||
| 		opts.Transport = transport.DefaultTransport | ||||
| 	} | ||||
|  | ||||
| 	if opts.DebugHandler == nil { | ||||
| 		opts.DebugHandler = debug.DefaultHandler | ||||
| 	} | ||||
|  | ||||
| 	if opts.RegisterCheck == nil { | ||||
| 		opts.RegisterCheck = DefaultRegisterCheck | ||||
| 	} | ||||
| @@ -156,13 +148,6 @@ func Transport(t transport.Transport) Option { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // DebugHandler for this server | ||||
| func DebugHandler(d debug.Handler) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.DebugHandler = d | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Metadata associated with the server | ||||
| func Metadata(md map[string]string) Option { | ||||
| 	return func(o *Options) { | ||||
|   | ||||
| @@ -485,7 +485,6 @@ func (s *rpcServer) Deregister() error { | ||||
| } | ||||
|  | ||||
| func (s *rpcServer) Start() error { | ||||
| 	registerDebugHandler(s) | ||||
| 	config := s.Options() | ||||
|  | ||||
| 	// start listening on the transport | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
|  | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/config/cmd" | ||||
| 	"github.com/micro/go-micro/debug/handler" | ||||
| 	"github.com/micro/go-micro/metadata" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| ) | ||||
| @@ -113,6 +114,14 @@ func (s *service) Stop() error { | ||||
| } | ||||
|  | ||||
| func (s *service) Run() error { | ||||
| 	// register the debug handler | ||||
| 	s.opts.Server.Handle( | ||||
| 		s.opts.Server.NewHandler( | ||||
| 			handler.DefaultHandler, | ||||
| 			server.InternalHandler(true), | ||||
| 		), | ||||
| 	) | ||||
|  | ||||
| 	if err := s.Start(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										220
									
								
								service/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								service/options.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,220 @@ | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/micro/go-micro/broker" | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/registry" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| 	"github.com/micro/go-micro/transport" | ||||
| ) | ||||
|  | ||||
| type Options struct { | ||||
| 	Broker    broker.Broker | ||||
| 	Client    client.Client | ||||
| 	Server    server.Server | ||||
| 	Registry  registry.Registry | ||||
| 	Transport transport.Transport | ||||
|  | ||||
| 	// Before and After funcs | ||||
| 	BeforeStart []func() error | ||||
| 	BeforeStop  []func() error | ||||
| 	AfterStart  []func() error | ||||
| 	AfterStop   []func() error | ||||
|  | ||||
| 	// Other options for implementations of the interface | ||||
| 	// can be stored in a context | ||||
| 	Context context.Context | ||||
| } | ||||
|  | ||||
| type Option func(*Options) | ||||
|  | ||||
| func newOptions(opts ...Option) Options { | ||||
| 	opt := Options{ | ||||
| 		Broker:    broker.DefaultBroker, | ||||
| 		Client:    client.DefaultClient, | ||||
| 		Server:    server.DefaultServer, | ||||
| 		Registry:  registry.DefaultRegistry, | ||||
| 		Transport: transport.DefaultTransport, | ||||
| 		Context:   context.Background(), | ||||
| 	} | ||||
|  | ||||
| 	for _, o := range opts { | ||||
| 		o(&opt) | ||||
| 	} | ||||
|  | ||||
| 	return opt | ||||
| } | ||||
|  | ||||
| func Broker(b broker.Broker) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Broker = b | ||||
| 		// Update Client and Server | ||||
| 		o.Client.Init(client.Broker(b)) | ||||
| 		o.Server.Init(server.Broker(b)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Client(c client.Client) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Client = c | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Context specifies a context for the service. | ||||
| // Can be used to signal shutdown of the service. | ||||
| // Can be used for extra option values. | ||||
| func Context(ctx context.Context) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Context = ctx | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Server(s server.Server) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server = s | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Registry sets the registry for the service | ||||
| // and the underlying components | ||||
| func Registry(r registry.Registry) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Registry = r | ||||
| 		// Update Client and Server | ||||
| 		o.Client.Init(client.Registry(r)) | ||||
| 		o.Server.Init(server.Registry(r)) | ||||
| 		// Update Broker | ||||
| 		o.Broker.Init(broker.Registry(r)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Transport sets the transport for the service | ||||
| // and the underlying components | ||||
| func Transport(t transport.Transport) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Transport = t | ||||
| 		// Update Client and Server | ||||
| 		o.Client.Init(client.Transport(t)) | ||||
| 		o.Server.Init(server.Transport(t)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Convenience options | ||||
|  | ||||
| // Address sets the address of the server | ||||
| func Address(addr string) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.Address(addr)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Name of the service | ||||
| func Name(n string) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.Name(n)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Version of the service | ||||
| func Version(v string) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.Version(v)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Metadata associated with the service | ||||
| func Metadata(md map[string]string) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.Metadata(md)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // RegisterTTL specifies the TTL to use when registering the service | ||||
| func RegisterTTL(t time.Duration) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.RegisterTTL(t)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // RegisterInterval specifies the interval on which to re-register | ||||
| func RegisterInterval(t time.Duration) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Server.Init(server.RegisterInterval(t)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WrapClient is a convenience method for wrapping a Client with | ||||
| // some middleware component. A list of wrappers can be provided. | ||||
| // Wrappers are applied in reverse order so the last is executed first. | ||||
| func WrapClient(w ...client.Wrapper) Option { | ||||
| 	return func(o *Options) { | ||||
| 		// apply in reverse | ||||
| 		for i := len(w); i > 0; i-- { | ||||
| 			o.Client = w[i-1](o.Client) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WrapCall is a convenience method for wrapping a Client CallFunc | ||||
| func WrapCall(w ...client.CallWrapper) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.Client.Init(client.WrapCall(w...)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WrapHandler adds a handler Wrapper to a list of options passed into the server | ||||
| func WrapHandler(w ...server.HandlerWrapper) Option { | ||||
| 	return func(o *Options) { | ||||
| 		var wrappers []server.Option | ||||
|  | ||||
| 		for _, wrap := range w { | ||||
| 			wrappers = append(wrappers, server.WrapHandler(wrap)) | ||||
| 		} | ||||
|  | ||||
| 		// Init once | ||||
| 		o.Server.Init(wrappers...) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // WrapSubscriber adds a subscriber Wrapper to a list of options passed into the server | ||||
| func WrapSubscriber(w ...server.SubscriberWrapper) Option { | ||||
| 	return func(o *Options) { | ||||
| 		var wrappers []server.Option | ||||
|  | ||||
| 		for _, wrap := range w { | ||||
| 			wrappers = append(wrappers, server.WrapSubscriber(wrap)) | ||||
| 		} | ||||
|  | ||||
| 		// Init once | ||||
| 		o.Server.Init(wrappers...) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Before and Afters | ||||
|  | ||||
| func BeforeStart(fn func() error) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.BeforeStart = append(o.BeforeStart, fn) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BeforeStop(fn func() error) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.BeforeStop = append(o.BeforeStop, fn) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func AfterStart(fn func() error) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.AfterStart = append(o.AfterStart, fn) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func AfterStop(fn func() error) Option { | ||||
| 	return func(o *Options) { | ||||
| 		o.AfterStop = append(o.AfterStop, fn) | ||||
| 	} | ||||
| } | ||||
| @@ -1,2 +1,16 @@ | ||||
| // Package service encapsulates the client, server and other interfaces to provide a complete micro service. | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	"github.com/micro/go-micro/server" | ||||
| ) | ||||
|  | ||||
| type Service interface { | ||||
| 	Init(...Option) | ||||
| 	Options() Options | ||||
| 	Client() client.Client | ||||
| 	Server() server.Server | ||||
| 	Run() error | ||||
| 	String() string | ||||
| } | ||||
|   | ||||
| @@ -8,8 +8,8 @@ import ( | ||||
|  | ||||
| 	glog "github.com/go-log/log" | ||||
| 	"github.com/micro/go-micro/client" | ||||
| 	proto "github.com/micro/go-micro/debug/proto" | ||||
| 	"github.com/micro/go-micro/registry/memory" | ||||
| 	proto "github.com/micro/go-micro/server/debug/proto" | ||||
| 	"github.com/micro/go-micro/util/log" | ||||
| ) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user