logger service

This commit is contained in:
Darien Raymond 2018-02-14 17:35:09 +01:00
parent 1e0b35f869
commit c48fa50ab1
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
9 changed files with 313 additions and 17 deletions

View File

@ -0,0 +1,50 @@
package command
//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg command -path App,Log,Command
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
"v2ray.com/core"
"v2ray.com/core/app/log"
"v2ray.com/core/common"
)
type LoggerServer struct {
V *core.Instance
}
func (s *LoggerServer) RestartLogger(ctx context.Context, request *RestartLoggerRequest) (*RestartLoggerResponse, error) {
logger := s.V.GetFeature((*log.Instance)(nil))
if logger == nil {
return nil, newError("unable to get logger instance")
}
if err := logger.Close(); err != nil {
return nil, newError("failed to close logger").Base(err)
}
if err := logger.Start(); err != nil {
return nil, newError("failed to start logger").Base(err)
}
return &RestartLoggerResponse{}, nil
}
type service struct {
v *core.Instance
}
func (s *service) Register(server *grpc.Server) {
RegisterLoggerServiceServer(server, &LoggerServer{
V: s.v,
})
}
func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
s := core.FromContext(ctx)
if s == nil {
return nil, newError("V is not in context.")
}
return &service{v: s}, nil
}))
}

View File

@ -0,0 +1,31 @@
package command_test
import (
"context"
"testing"
"v2ray.com/core"
"v2ray.com/core/app/log"
. "v2ray.com/core/app/log/command"
"v2ray.com/core/common/serial"
. "v2ray.com/ext/assert"
)
func TestLoggerRestart(t *testing.T) {
assert := With(t)
v, err := core.New(&core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{}),
},
})
assert(err, IsNil)
assert(v.Start(), IsNil)
server := &LoggerServer{
V: v,
}
_, err = server.RestartLogger(context.Background(), &RestartLoggerRequest{})
assert(err, IsNil)
}

View File

@ -0,0 +1,143 @@
package command
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// 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 Config struct {
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type RestartLoggerRequest struct {
}
func (m *RestartLoggerRequest) Reset() { *m = RestartLoggerRequest{} }
func (m *RestartLoggerRequest) String() string { return proto.CompactTextString(m) }
func (*RestartLoggerRequest) ProtoMessage() {}
func (*RestartLoggerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
type RestartLoggerResponse struct {
}
func (m *RestartLoggerResponse) Reset() { *m = RestartLoggerResponse{} }
func (m *RestartLoggerResponse) String() string { return proto.CompactTextString(m) }
func (*RestartLoggerResponse) ProtoMessage() {}
func (*RestartLoggerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func init() {
proto.RegisterType((*Config)(nil), "v2ray.core.app.log.command.Config")
proto.RegisterType((*RestartLoggerRequest)(nil), "v2ray.core.app.log.command.RestartLoggerRequest")
proto.RegisterType((*RestartLoggerResponse)(nil), "v2ray.core.app.log.command.RestartLoggerResponse")
}
// 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
// Client API for LoggerService service
type LoggerServiceClient interface {
RestartLogger(ctx context.Context, in *RestartLoggerRequest, opts ...grpc.CallOption) (*RestartLoggerResponse, error)
}
type loggerServiceClient struct {
cc *grpc.ClientConn
}
func NewLoggerServiceClient(cc *grpc.ClientConn) LoggerServiceClient {
return &loggerServiceClient{cc}
}
func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLoggerRequest, opts ...grpc.CallOption) (*RestartLoggerResponse, error) {
out := new(RestartLoggerResponse)
err := grpc.Invoke(ctx, "/v2ray.core.app.log.command.LoggerService/RestartLogger", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for LoggerService service
type LoggerServiceServer interface {
RestartLogger(context.Context, *RestartLoggerRequest) (*RestartLoggerResponse, error)
}
func RegisterLoggerServiceServer(s *grpc.Server, srv LoggerServiceServer) {
s.RegisterService(&_LoggerService_serviceDesc, srv)
}
func _LoggerService_RestartLogger_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RestartLoggerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(LoggerServiceServer).RestartLogger(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/v2ray.core.app.log.command.LoggerService/RestartLogger",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LoggerServiceServer).RestartLogger(ctx, req.(*RestartLoggerRequest))
}
return interceptor(ctx, in, info, handler)
}
var _LoggerService_serviceDesc = grpc.ServiceDesc{
ServiceName: "v2ray.core.app.log.command.LoggerService",
HandlerType: (*LoggerServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "RestartLogger",
Handler: _LoggerService_RestartLogger_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "v2ray.com/core/app/log/command/config.proto",
}
func init() { proto.RegisterFile("v2ray.com/core/app/log/command/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 210 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x2e, 0x33, 0x2a, 0x4a,
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0x2c, 0x28, 0xd0, 0xcf,
0xc9, 0x4f, 0xd7, 0x4f, 0xce, 0xcf, 0xcd, 0x4d, 0xcc, 0x4b, 0xd1, 0x4f, 0xce, 0xcf, 0x4b, 0xcb,
0x4c, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x82, 0x29, 0x2e, 0x4a, 0xd5, 0x4b, 0x2c,
0x28, 0xd0, 0xcb, 0xc9, 0x4f, 0xd7, 0x83, 0x2a, 0x54, 0xe2, 0xe0, 0x62, 0x73, 0x06, 0xab, 0x55,
0x12, 0xe3, 0x12, 0x09, 0x4a, 0x2d, 0x2e, 0x49, 0x2c, 0x2a, 0xf1, 0xc9, 0x4f, 0x4f, 0x4f, 0x2d,
0x0a, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x51, 0x12, 0xe7, 0x12, 0x45, 0x13, 0x2f, 0x2e, 0xc8,
0xcf, 0x2b, 0x4e, 0x35, 0x6a, 0x67, 0xe4, 0xe2, 0x85, 0x08, 0x05, 0xa7, 0x16, 0x95, 0x65, 0x26,
0xa7, 0x0a, 0x95, 0x71, 0xf1, 0xa2, 0x28, 0x15, 0x32, 0xd0, 0xc3, 0x6d, 0xb5, 0x1e, 0x36, 0xdb,
0xa4, 0x0c, 0x49, 0xd0, 0x01, 0x71, 0x87, 0x12, 0x83, 0x93, 0x07, 0x97, 0x5c, 0x72, 0x7e, 0x2e,
0x1e, 0x9d, 0x01, 0x8c, 0x51, 0xec, 0x50, 0xe6, 0x2a, 0x26, 0xa9, 0x30, 0xa3, 0xa0, 0xc4, 0x4a,
0x3d, 0x67, 0x90, 0x3a, 0xc7, 0x82, 0x02, 0x3d, 0x9f, 0xfc, 0x74, 0x3d, 0x67, 0x88, 0x64, 0x12,
0x1b, 0x38, 0xc4, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x37, 0xc7, 0xfc, 0xda, 0x60, 0x01,
0x00, 0x00,
}

View File

@ -0,0 +1,18 @@
syntax = "proto3";
package v2ray.core.app.log.command;
option csharp_namespace = "V2Ray.Core.App.Log.Command";
option go_package = "command";
option java_package = "com.v2ray.core.app.log.command";
option java_multiple_files = true;
message Config {
}
message RestartLoggerRequest {}
message RestartLoggerResponse{}
service LoggerService {
rpc RestartLogger(RestartLoggerRequest) returns (RestartLoggerResponse) {}
}

View File

@ -0,0 +1,5 @@
package command
import "v2ray.com/core/common/errors"
func newError(values ...interface{}) *errors.Error { return errors.New(values...).Path("App", "Log", "Command") }

View File

@ -6,6 +6,7 @@ import (
"context"
"sync"
"v2ray.com/core"
"v2ray.com/core/common"
"v2ray.com/core/common/log"
)
@ -26,13 +27,10 @@ func New(ctx context.Context, config *Config) (*Instance, error) {
active: true,
}
if err := g.initAccessLogger(); err != nil {
return nil, newError("failed to initialize access logger").Base(err).AtWarning()
v := core.FromContext(ctx)
if v != nil {
common.Must(v.RegisterFeature((*log.Handler)(nil), g))
}
if err := g.initErrorLogger(); err != nil {
return nil, newError("failed to initialize error logger").Base(err).AtWarning()
}
log.RegisterHandler(g)
return g, nil
}
@ -67,24 +65,40 @@ func (g *Instance) initErrorLogger() error {
return nil
}
// Start implements app.Application.Start().
func (g *Instance) Start() error {
g.Lock()
defer g.Unlock()
g.active = true
return nil
func (*Instance) Type() interface{} {
return (*Instance)(nil)
}
func (g *Instance) isActive() bool {
g.RLock()
defer g.RUnlock()
// Start implements app.Application.Start().
func (g *Instance) Start() error {
newError("Logger starting").AtDebug().WriteToLog()
return g.active
g.Lock()
defer g.Unlock()
if g.active {
return nil
}
g.active = true
if err := g.initAccessLogger(); err != nil {
return newError("failed to initialize access logger").Base(err).AtWarning()
}
if err := g.initErrorLogger(); err != nil {
return newError("failed to initialize error logger").Base(err).AtWarning()
}
log.RegisterHandler(g)
return nil
}
// Handle implements log.Handler.
func (g *Instance) Handle(msg log.Message) {
if !g.isActive() {
g.RLock()
defer g.RUnlock()
if !g.active {
return
}
@ -104,11 +118,20 @@ func (g *Instance) Handle(msg log.Message) {
// Close implement app.Application.Close().
func (g *Instance) Close() error {
newError("Logger closing").AtDebug().WriteToLog()
g.Lock()
defer g.Unlock()
if !g.active {
return nil
}
g.active = false
common.Close(g.accessLogger)
common.Close(g.errorLogger)
return nil
}

View File

@ -21,3 +21,9 @@ type Runnable interface {
Closable
}
// HasType is the interface for objects that knows its type.
type HasType interface {
// Type returns the type of the object.
Type() interface{}
}

View File

@ -23,6 +23,7 @@ type generalLogger struct {
creator WriterCreator
buffer chan Message
access *signal.Semaphore
done *signal.Done
}
// NewLogger returns a generic log handler that can handle all type of messages.
@ -31,6 +32,7 @@ func NewLogger(logWriterCreator WriterCreator) Handler {
creator: logWriterCreator,
buffer: make(chan Message, 16),
access: signal.NewSemaphore(1),
done: signal.NewDone(),
}
}
@ -49,6 +51,8 @@ func (l *generalLogger) run() {
for {
select {
case <-l.done.C():
return
case msg := <-l.buffer:
logger.Write(msg.String() + platform.LineSeparator())
dataWritten = true
@ -74,6 +78,10 @@ func (l *generalLogger) Handle(msg Message) {
}
}
func (l *generalLogger) Close() error {
return l.done.Close()
}
type consoleLogWriter struct {
logger *log.Logger
}

View File

@ -163,6 +163,18 @@ func (s *Instance) RegisterFeature(feature interface{}, instance Feature) error
return nil
}
// GetFeature returns a feature that was registered in this Instance. Nil if not found.
func (s *Instance) GetFeature(featureType interface{}) Feature {
for _, f := range s.features {
if hasType, ok := f.(common.HasType); ok {
if hasType.Type() == featureType {
return f
}
}
}
return nil
}
// DNSClient returns the DNSClient used by this Instance. The returned DNSClient is always functional.
func (s *Instance) DNSClient() DNSClient {
return &(s.dnsClient)