ソースを参照

merge log into common log

Darien Raymond 8 年 前
コミット
f4c35db968
45 ファイル変更292 行追加401 行削除
  1. 4 5
      app/dispatcher/impl/default.go
  2. 1 3
      app/dns/config.go
  3. 5 6
      app/dns/server/nameserver.go
  4. 2 3
      app/dns/server/server.go
  5. 0 35
      app/log/access.go
  6. 28 59
      app/log/config.pb.go
  7. 3 9
      app/log/config.proto
  8. 0 32
      app/log/internal/log_entry.go
  9. 0 25
      app/log/internal/log_entry_test.go
  10. 4 7
      app/log/internal/log_writer.go
  11. 67 84
      app/log/log.go
  12. 1 2
      app/proxyman/inbound/always.go
  13. 3 4
      app/proxyman/inbound/dynamic.go
  14. 3 4
      app/proxyman/inbound/worker.go
  15. 10 11
      app/proxyman/mux/mux.go
  16. 4 5
      app/proxyman/outbound/handler.go
  17. 1 2
      app/router/router.go
  18. 14 0
      common/errors/errors.go
  19. 10 0
      common/log/access.go
  20. 4 0
      common/log/log.go
  21. 2 3
      common/net/address.go
  22. 1 2
      plugin_linux.go
  23. 1 2
      proxy/dokodemo/dokodemo.go
  24. 2 3
      proxy/freedom/freedom.go
  25. 8 4
      proxy/http/server.go
  26. 1 2
      proxy/shadowsocks/client.go
  27. 31 11
      proxy/shadowsocks/server.go
  28. 25 10
      proxy/socks/server.go
  29. 1 2
      proxy/vmess/account.go
  30. 3 4
      proxy/vmess/encoding/client.go
  31. 19 8
      proxy/vmess/inbound/inbound.go
  32. 1 2
      proxy/vmess/outbound/outbound.go
  33. 9 4
      testing/scenarios/common.go
  34. 5 6
      transport/internet/kcp/connection.go
  35. 1 2
      transport/internet/kcp/dialer.go
  36. 2 3
      transport/internet/kcp/listener.go
  37. 1 2
      transport/internet/tcp/dialer.go
  38. 2 3
      transport/internet/tcp/hub.go
  39. 1 2
      transport/internet/tcp/sockopt_linux.go
  40. 1 2
      transport/internet/tls/config.go
  41. 4 5
      transport/internet/udp/dispatcher.go
  42. 3 4
      transport/internet/udp/hub.go
  43. 1 2
      transport/internet/websocket/dialer.go
  44. 2 3
      transport/internet/websocket/hub.go
  45. 1 14
      v2ray.go

+ 4 - 5
app/dispatcher/impl/default.go

@@ -8,7 +8,6 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/app/router"
 	"v2ray.com/core/common"
@@ -78,7 +77,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
 		go func() {
 			domain, err := snifer(ctx, sniferList, outbound)
 			if err == nil {
-				log.Trace(newError("sniffed domain: ", domain))
+				newError("sniffed domain: ", domain).WriteToLog()
 				destination.Address = net.ParseAddress(domain)
 				ctx = proxy.ContextWithTarget(ctx, destination)
 			}
@@ -123,13 +122,13 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, outbound ray.Out
 	if d.router != nil {
 		if tag, err := d.router.TakeDetour(ctx); err == nil {
 			if handler := d.ohm.GetHandler(tag); handler != nil {
-				log.Trace(newError("taking detour [", tag, "] for [", destination, "]"))
+				newError("taking detour [", tag, "] for [", destination, "]").WriteToLog()
 				dispatcher = handler
 			} else {
-				log.Trace(newError("nonexisting tag: ", tag).AtWarning())
+				newError("nonexisting tag: ", tag).AtWarning().WriteToLog()
 			}
 		} else {
-			log.Trace(newError("default route for ", destination))
+			newError("default route for ", destination).WriteToLog()
 		}
 	}
 	dispatcher.Dispatch(ctx, outbound)

+ 1 - 3
app/dns/config.go

@@ -2,8 +2,6 @@ package dns
 
 import (
 	"net"
-
-	"v2ray.com/core/app/log"
 )
 
 func (c *Config) GetInternalHosts() map[string]net.IP {
@@ -11,7 +9,7 @@ func (c *Config) GetInternalHosts() map[string]net.IP {
 	for domain, ipOrDomain := range c.GetHosts() {
 		address := ipOrDomain.AsAddress()
 		if address.Family().IsDomain() {
-			log.Trace(newError("ignoring domain address in static hosts: ", address.Domain()).AtWarning())
+			newError("ignoring domain address in static hosts: ", address.Domain()).AtWarning().WriteToLog()
 			continue
 		}
 		hosts[domain] = address.IP()

+ 5 - 6
app/dns/server/nameserver.go

@@ -7,7 +7,6 @@ import (
 
 	"github.com/miekg/dns"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/dice"
@@ -88,7 +87,7 @@ func (s *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 {
 		if _, found := s.requests[id]; found {
 			continue
 		}
-		log.Trace(newError("add pending request id ", id).AtDebug())
+		newError("add pending request id ", id).AtDebug().WriteToLog()
 		s.requests[id] = &PendingRequest{
 			expire:   time.Now().Add(time.Second * 8),
 			response: response,
@@ -103,9 +102,9 @@ func (s *UDPNameServer) HandleResponse(payload *buf.Buffer) {
 	msg := new(dns.Msg)
 	err := msg.Unpack(payload.Bytes())
 	if err == dns.ErrTruncated {
-		log.Trace(newError("truncated message received. DNS server should still work. If you see anything abnormal, please submit an issue to v2ray-core.").AtWarning())
+		newError("truncated message received. DNS server should still work. If you see anything abnormal, please submit an issue to v2ray-core.").AtWarning().WriteToLog()
 	} else if err != nil {
-		log.Trace(newError("failed to parse DNS response").Base(err).AtWarning())
+		newError("failed to parse DNS response").Base(err).AtWarning().WriteToLog()
 		return
 	}
 	record := &ARecord{
@@ -113,7 +112,7 @@ func (s *UDPNameServer) HandleResponse(payload *buf.Buffer) {
 	}
 	id := msg.Id
 	ttl := uint32(3600) // an hour
-	log.Trace(newError("handling response for id ", id, " content: ", msg).AtDebug())
+	newError("handling response for id ", id, " content: ", msg).AtDebug().WriteToLog()
 
 	s.Lock()
 	request, found := s.requests[id]
@@ -206,7 +205,7 @@ func (*LocalNameServer) QueryA(domain string) <-chan *ARecord {
 
 		ips, err := net.LookupIP(domain)
 		if err != nil {
-			log.Trace(newError("failed to lookup IPs for domain ", domain).Base(err))
+			newError("failed to lookup IPs for domain ", domain).Base(err).WriteToLog()
 			return
 		}
 

+ 2 - 3
app/dns/server/server.go

@@ -11,7 +11,6 @@ import (
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/app/dns"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 )
@@ -144,13 +143,13 @@ func (s *CacheServer) Get(domain string) []net.IP {
 				LastAccess: time.Now(),
 			}
 			s.Unlock()
-			log.Trace(newError("returning ", len(a.IPs), " IPs for domain ", domain).AtDebug())
+			newError("returning ", len(a.IPs), " IPs for domain ", domain).AtDebug().WriteToLog()
 			return a.IPs
 		case <-time.After(QueryTimeout):
 		}
 	}
 
-	log.Trace(newError("returning nil for domain ", domain).AtDebug())
+	newError("returning nil for domain ", domain).AtDebug().WriteToLog()
 	return nil
 }
 

+ 0 - 35
app/log/access.go

@@ -1,35 +0,0 @@
-package log
-
-import "v2ray.com/core/app/log/internal"
-
-// AccessStatus is the status of an access request from clients.
-type AccessStatus string
-
-const (
-	AccessAccepted = AccessStatus("accepted")
-	AccessRejected = AccessStatus("rejected")
-)
-
-var (
-	accessLoggerInstance internal.LogWriter = new(internal.NoOpLogWriter)
-)
-
-// InitAccessLogger initializes the access logger to write into the give file.
-func InitAccessLogger(file string) error {
-	logger, err := internal.NewFileLogWriter(file)
-	if err != nil {
-		return newError("failed to create access logger on file: ", file).Base(err)
-	}
-	accessLoggerInstance = logger
-	return nil
-}
-
-// Access writes an access log.
-func Access(from, to interface{}, status AccessStatus, reason interface{}) {
-	accessLoggerInstance.Log(&internal.AccessLog{
-		From:   from,
-		To:     to,
-		Status: string(status),
-		Reason: reason,
-	})
-}

+ 28 - 59
app/log/config.pb.go

@@ -3,6 +3,7 @@ package log
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import math "math"
+import v2ray_core_common_log "v2ray.com/core/common/log"
 
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
@@ -42,42 +43,12 @@ func (x LogType) String() string {
 }
 func (LogType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
 
-type LogLevel int32
-
-const (
-	LogLevel_Disabled LogLevel = 0
-	LogLevel_Error    LogLevel = 1
-	LogLevel_Warning  LogLevel = 2
-	LogLevel_Info     LogLevel = 3
-	LogLevel_Debug    LogLevel = 4
-)
-
-var LogLevel_name = map[int32]string{
-	0: "Disabled",
-	1: "Error",
-	2: "Warning",
-	3: "Info",
-	4: "Debug",
-}
-var LogLevel_value = map[string]int32{
-	"Disabled": 0,
-	"Error":    1,
-	"Warning":  2,
-	"Info":     3,
-	"Debug":    4,
-}
-
-func (x LogLevel) String() string {
-	return proto.EnumName(LogLevel_name, int32(x))
-}
-func (LogLevel) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
-
 type Config struct {
-	ErrorLogType  LogType  `protobuf:"varint,1,opt,name=error_log_type,json=errorLogType,enum=v2ray.core.app.log.LogType" json:"error_log_type,omitempty"`
-	ErrorLogLevel LogLevel `protobuf:"varint,2,opt,name=error_log_level,json=errorLogLevel,enum=v2ray.core.app.log.LogLevel" json:"error_log_level,omitempty"`
-	ErrorLogPath  string   `protobuf:"bytes,3,opt,name=error_log_path,json=errorLogPath" json:"error_log_path,omitempty"`
-	AccessLogType LogType  `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,enum=v2ray.core.app.log.LogType" json:"access_log_type,omitempty"`
-	AccessLogPath string   `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath" json:"access_log_path,omitempty"`
+	ErrorLogType  LogType                        `protobuf:"varint,1,opt,name=error_log_type,json=errorLogType,enum=v2ray.core.app.log.LogType" json:"error_log_type,omitempty"`
+	ErrorLogLevel v2ray_core_common_log.Severity `protobuf:"varint,2,opt,name=error_log_level,json=errorLogLevel,enum=v2ray.core.common.log.Severity" json:"error_log_level,omitempty"`
+	ErrorLogPath  string                         `protobuf:"bytes,3,opt,name=error_log_path,json=errorLogPath" json:"error_log_path,omitempty"`
+	AccessLogType LogType                        `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,enum=v2ray.core.app.log.LogType" json:"access_log_type,omitempty"`
+	AccessLogPath string                         `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath" json:"access_log_path,omitempty"`
 }
 
 func (m *Config) Reset()                    { *m = Config{} }
@@ -92,11 +63,11 @@ func (m *Config) GetErrorLogType() LogType {
 	return LogType_None
 }
 
-func (m *Config) GetErrorLogLevel() LogLevel {
+func (m *Config) GetErrorLogLevel() v2ray_core_common_log.Severity {
 	if m != nil {
 		return m.ErrorLogLevel
 	}
-	return LogLevel_Disabled
+	return v2ray_core_common_log.Severity_Unknown
 }
 
 func (m *Config) GetErrorLogPath() string {
@@ -123,32 +94,30 @@ func (m *Config) GetAccessLogPath() string {
 func init() {
 	proto.RegisterType((*Config)(nil), "v2ray.core.app.log.Config")
 	proto.RegisterEnum("v2ray.core.app.log.LogType", LogType_name, LogType_value)
-	proto.RegisterEnum("v2ray.core.app.log.LogLevel", LogLevel_name, LogLevel_value)
 }
 
 func init() { proto.RegisterFile("v2ray.com/core/app/log/config.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-	// 331 bytes of a gzipped FileDescriptorProto
+	// 306 bytes of a gzipped FileDescriptorProto
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0xcd, 0x4a, 0xfb, 0x40,
-	0x14, 0xc5, 0x9b, 0xa4, 0x9f, 0xf3, 0xef, 0xc7, 0x30, 0x8b, 0x3f, 0x05, 0x5d, 0x14, 0x15, 0x29,
-	0x5d, 0x24, 0x50, 0xf5, 0x01, 0x6a, 0x5a, 0x41, 0x28, 0x52, 0x8a, 0x28, 0xb8, 0x29, 0xd3, 0x78,
-	0x3b, 0x0d, 0x4c, 0x73, 0x87, 0x49, 0x2c, 0xe4, 0x7d, 0x5c, 0xf9, 0x94, 0x32, 0xa3, 0x31, 0x8a,
-	0x8a, 0xcb, 0x9b, 0x9c, 0xf3, 0x3b, 0xe7, 0x30, 0xe4, 0x78, 0x3f, 0xd6, 0x3c, 0xf7, 0x23, 0xdc,
-	0x05, 0x11, 0x6a, 0x08, 0xb8, 0x52, 0x81, 0x44, 0x11, 0x44, 0x98, 0x6c, 0x62, 0xe1, 0x2b, 0x8d,
-	0x19, 0x32, 0x56, 0x88, 0x34, 0xf8, 0x5c, 0x29, 0x5f, 0xa2, 0x38, 0x7a, 0x76, 0x49, 0x3d, 0xb4,
-	0x22, 0x36, 0x21, 0x5d, 0xd0, 0x1a, 0xf5, 0x4a, 0xa2, 0x58, 0x65, 0xb9, 0x82, 0xbe, 0x33, 0x70,
-	0x86, 0xdd, 0xf1, 0x81, 0xff, 0xdd, 0xe7, 0xcf, 0x51, 0xdc, 0xe6, 0x0a, 0x96, 0x6d, 0x6b, 0x79,
-	0xbf, 0xd8, 0x94, 0xf4, 0x4a, 0x84, 0x84, 0x3d, 0xc8, 0xbe, 0x6b, 0x19, 0x87, 0xbf, 0x30, 0xe6,
-	0x46, 0xb3, 0xec, 0x14, 0x10, 0x7b, 0xb2, 0x93, 0xcf, 0x45, 0x14, 0xcf, 0xb6, 0x7d, 0x6f, 0xe0,
-	0x0c, 0x5b, 0x65, 0xd6, 0x82, 0x67, 0x5b, 0x16, 0x92, 0x1e, 0x8f, 0x22, 0x48, 0xd3, 0xb2, 0x6f,
-	0xf5, 0xef, 0xbe, 0x9d, 0x37, 0x4f, 0x51, 0xf8, 0xf4, 0x0b, 0xc4, 0x66, 0xd5, 0x6c, 0x56, 0xa9,
-	0x33, 0x61, 0xa3, 0x0b, 0xd2, 0x28, 0x2c, 0x4d, 0x52, 0xbd, 0xc1, 0x04, 0x68, 0x85, 0xfd, 0x23,
-	0x8d, 0x10, 0x93, 0x14, 0x25, 0x50, 0xc7, 0x7c, 0xbe, 0x8a, 0x25, 0x50, 0x97, 0xb5, 0x48, 0x6d,
-	0xb6, 0x87, 0x24, 0xa3, 0xde, 0x68, 0x46, 0x9a, 0x1f, 0xab, 0xda, 0xa4, 0x39, 0x8d, 0x53, 0xbe,
-	0x96, 0xf0, 0x48, 0x2b, 0x56, 0x64, 0xd6, 0x50, 0xc7, 0x60, 0xee, 0xb9, 0x4e, 0xe2, 0x44, 0x50,
-	0xd7, 0x60, 0xae, 0x93, 0x0d, 0x52, 0xcf, 0x28, 0xa6, 0xb0, 0x7e, 0x12, 0xb4, 0x7a, 0x79, 0x4e,
-	0xfe, 0x47, 0xb8, 0xfb, 0x61, 0xd6, 0xc2, 0x79, 0xf0, 0x24, 0x8a, 0x17, 0x97, 0xdd, 0x8d, 0x97,
-	0x3c, 0xf7, 0x43, 0xf3, 0x6f, 0xa2, 0x94, 0x99, 0xbb, 0xae, 0xdb, 0x57, 0x3f, 0x7b, 0x0d, 0x00,
-	0x00, 0xff, 0xff, 0x93, 0x6e, 0xe5, 0xbd, 0x1c, 0x02, 0x00, 0x00,
+	0x14, 0x47, 0xff, 0x49, 0xbf, 0xfe, 0x1d, 0x6d, 0x1b, 0x66, 0x21, 0x45, 0x17, 0x16, 0x15, 0x29,
+	0x2e, 0x26, 0x50, 0xf5, 0x01, 0x6a, 0x50, 0x37, 0x45, 0x4a, 0x14, 0x17, 0x6e, 0xca, 0x38, 0x5c,
+	0xa7, 0x81, 0x49, 0xee, 0x30, 0x19, 0x02, 0x79, 0x22, 0xc1, 0xa7, 0x94, 0x4c, 0x1b, 0x52, 0x3f,
+	0xc0, 0x65, 0x92, 0x7b, 0xce, 0xef, 0x40, 0xc8, 0x69, 0x31, 0x33, 0xbc, 0x64, 0x02, 0xd3, 0x50,
+	0xa0, 0x81, 0x90, 0x6b, 0x1d, 0x2a, 0x94, 0xa1, 0xc0, 0xec, 0x2d, 0x91, 0x4c, 0x1b, 0xb4, 0x48,
+	0x69, 0x7d, 0x64, 0x80, 0x71, 0xad, 0x99, 0x42, 0x79, 0xf8, 0x1d, 0x14, 0x98, 0xa6, 0x98, 0x39,
+	0x56, 0xe1, 0x16, 0x3c, 0x79, 0xf7, 0x49, 0x37, 0x72, 0x26, 0x3a, 0x27, 0x43, 0x30, 0x06, 0xcd,
+	0x4a, 0xa1, 0x5c, 0xd9, 0x52, 0xc3, 0xd8, 0x9b, 0x78, 0xd3, 0xe1, 0xec, 0x88, 0xfd, 0x94, 0xb3,
+	0x05, 0xca, 0xa7, 0x52, 0x43, 0xbc, 0xef, 0x90, 0xed, 0x13, 0xbd, 0x27, 0xa3, 0x46, 0xa1, 0xa0,
+	0x00, 0x35, 0xf6, 0x9d, 0xe3, 0x78, 0xd7, 0xb1, 0x09, 0x71, 0x9a, 0x47, 0x28, 0xc0, 0x24, 0xb6,
+	0x8c, 0x07, 0xb5, 0x67, 0x51, 0x51, 0xf4, 0x6c, 0xb7, 0x45, 0x73, 0xbb, 0x1e, 0xb7, 0x26, 0xde,
+	0xb4, 0xdf, 0xcc, 0x2d, 0xb9, 0x5d, 0xd3, 0x88, 0x8c, 0xb8, 0x10, 0x90, 0xe7, 0x4d, 0x72, 0xfb,
+	0xef, 0xe4, 0xc1, 0x86, 0xa9, 0x9b, 0xcf, 0xbf, 0x48, 0xdc, 0x56, 0xc7, 0x6d, 0x35, 0x77, 0xd5,
+	0xd8, 0xc5, 0x35, 0xe9, 0xd5, 0xc8, 0x7f, 0xd2, 0x7e, 0xc0, 0x0c, 0x82, 0x7f, 0x74, 0x8f, 0xf4,
+	0x22, 0xcc, 0x72, 0x54, 0x10, 0x78, 0xd5, 0xeb, 0xbb, 0x44, 0x41, 0xe0, 0xd3, 0x3e, 0xe9, 0xdc,
+	0x16, 0x90, 0xd9, 0xa0, 0x75, 0x73, 0x45, 0x0e, 0x04, 0xa6, 0xbf, 0xf4, 0x2c, 0xbd, 0x97, 0x96,
+	0x42, 0xf9, 0xe1, 0xd3, 0xe7, 0x59, 0xcc, 0x4b, 0x16, 0x55, 0xdf, 0xe6, 0x5a, 0x57, 0x9d, 0xaf,
+	0x5d, 0xf7, 0x77, 0x2e, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x33, 0xd5, 0x99, 0x3f, 0xfd, 0x01,
+	0x00, 0x00,
 }

+ 3 - 9
app/log/config.proto

@@ -6,6 +6,8 @@ option go_package = "log";
 option java_package = "com.v2ray.core.app.log";
 option java_multiple_files = true;
 
+import "v2ray.com/core/common/log/log.proto";
+
 enum LogType {
   None = 0;
   Console = 1;
@@ -13,17 +15,9 @@ enum LogType {
   Event = 3;
 }
 
-enum LogLevel {
-  Disabled = 0;
-  Error = 1;
-  Warning = 2;
-  Info = 3;
-  Debug = 4;
-}
-
 message Config {
   LogType error_log_type = 1;
-  LogLevel error_log_level = 2;
+  v2ray.core.common.log.Severity error_log_level = 2;
   string error_log_path = 3;
 
   LogType access_log_type = 4;

+ 0 - 32
app/log/internal/log_entry.go

@@ -1,32 +0,0 @@
-package internal
-
-import (
-	"fmt"
-	"strings"
-
-	"v2ray.com/core/common/serial"
-)
-
-type LogEntry interface {
-	fmt.Stringer
-}
-
-type ErrorLog struct {
-	Prefix string
-	Error  error
-}
-
-func (l *ErrorLog) String() string {
-	return l.Prefix + l.Error.Error()
-}
-
-type AccessLog struct {
-	From   interface{}
-	To     interface{}
-	Status string
-	Reason interface{}
-}
-
-func (l *AccessLog) String() string {
-	return strings.Join([]string{serial.ToString(l.From), l.Status, serial.ToString(l.To), serial.ToString(l.Reason)}, " ")
-}

+ 0 - 25
app/log/internal/log_entry_test.go

@@ -1,25 +0,0 @@
-package internal_test
-
-import (
-	"testing"
-
-	. "v2ray.com/core/app/log/internal"
-	. "v2ray.com/ext/assert"
-)
-
-func TestAccessLog(t *testing.T) {
-	assert := With(t)
-
-	entry := &AccessLog{
-		From:   "test_from",
-		To:     "test_to",
-		Status: "Accepted",
-		Reason: "test_reason",
-	}
-
-	entryStr := entry.String()
-	assert(entryStr, HasSubstring, "test_from")
-	assert(entryStr, HasSubstring, "test_to")
-	assert(entryStr, HasSubstring, "test_reason")
-	assert(entryStr, HasSubstring, "Accepted")
-}

+ 4 - 7
app/log/internal/log_writer.go

@@ -8,18 +8,15 @@ import (
 	"v2ray.com/core/common/platform"
 )
 
+type LogEntry interface {
+	String() string
+}
+
 type LogWriter interface {
 	Log(LogEntry)
 	Close()
 }
 
-type NoOpLogWriter struct {
-}
-
-func (*NoOpLogWriter) Log(entry LogEntry) {}
-
-func (*NoOpLogWriter) Close() {}
-
 type StdOutLogWriter struct {
 	logger *log.Logger
 }

+ 67 - 84
app/log/log.go

@@ -4,118 +4,101 @@ package log
 
 import (
 	"context"
+	"sync"
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/log/internal"
 	"v2ray.com/core/common"
-	"v2ray.com/core/common/errors"
 	"v2ray.com/core/common/log"
 )
 
-var (
-	streamLoggerInstance internal.LogWriter = internal.NewStdOutLogWriter()
-
-	debugLogger   internal.LogWriter = streamLoggerInstance
-	infoLogger    internal.LogWriter = streamLoggerInstance
-	warningLogger internal.LogWriter = streamLoggerInstance
-	errorLogger   internal.LogWriter = streamLoggerInstance
-)
-
-func SetLogLevel(level LogLevel) {
-	debugLogger = new(internal.NoOpLogWriter)
-	if level >= LogLevel_Debug {
-		debugLogger = streamLoggerInstance
-	}
-
-	infoLogger = new(internal.NoOpLogWriter)
-	if level >= LogLevel_Info {
-		infoLogger = streamLoggerInstance
-	}
+type Instance struct {
+	sync.RWMutex
+	config       *Config
+	accessLogger internal.LogWriter
+	errorLogger  internal.LogWriter
+}
 
-	warningLogger = new(internal.NoOpLogWriter)
-	if level >= LogLevel_Warning {
-		warningLogger = streamLoggerInstance
-	}
+func New(ctx context.Context, config *Config) (*Instance, error) {
+	return &Instance{
+		config: config,
+	}, nil
+}
 
-	errorLogger = new(internal.NoOpLogWriter)
-	if level >= LogLevel_Error {
-		errorLogger = streamLoggerInstance
-	}
+func (*Instance) Interface() interface{} {
+	return (*Instance)(nil)
 }
 
-func InitErrorLogger(file string) error {
-	logger, err := internal.NewFileLogWriter(file)
-	if err != nil {
-		return newError("failed to create error logger on file (", file, ")").Base(err)
+func (g *Instance) initAccessLogger() error {
+	switch g.config.AccessLogType {
+	case LogType_File:
+		logger, err := internal.NewFileLogWriter(g.config.AccessLogPath)
+		if err != nil {
+			return err
+		}
+		g.accessLogger = logger
+	case LogType_Console:
+		g.accessLogger = internal.NewStdOutLogWriter()
+	default:
 	}
-	streamLoggerInstance = logger
 	return nil
 }
 
-func getLoggerAndPrefix(s log.Severity) (internal.LogWriter, string) {
-	switch s {
-	case log.Severity_Debug:
-		return debugLogger, "[Debug]"
-	case log.Severity_Info:
-		return infoLogger, "[Info]"
-	case log.Severity_Warning:
-		return warningLogger, "[Warning]"
-	case log.Severity_Error:
-		return errorLogger, "[Error]"
+func (g *Instance) initErrorLogger() error {
+	switch g.config.ErrorLogType {
+	case LogType_File:
+		logger, err := internal.NewFileLogWriter(g.config.ErrorLogPath)
+		if err != nil {
+			return err
+		}
+		g.errorLogger = logger
+	case LogType_Console:
+		g.errorLogger = internal.NewStdOutLogWriter()
 	default:
-		return infoLogger, "[Info]"
 	}
+	return nil
 }
 
-// Trace logs an error message based on its severity.
-func Trace(err error) {
-	if err == nil {
-		return
+func (g *Instance) Start() error {
+	if err := g.initAccessLogger(); err != nil {
+		return newError("failed to initialize access logger").Base(err).AtWarning()
 	}
-	logger, prefix := getLoggerAndPrefix(errors.GetSeverity(err))
-	logger.Log(&internal.ErrorLog{
-		Prefix: prefix,
-		Error:  err,
-	})
-}
-
-type Instance struct {
-	config *Config
-}
-
-func New(ctx context.Context, config *Config) (*Instance, error) {
-	return &Instance{config: config}, nil
-}
-
-func (*Instance) Interface() interface{} {
-	return (*Instance)(nil)
+	if err := g.initErrorLogger(); err != nil {
+		return newError("failed to initialize error logger").Base(err).AtWarning()
+	}
+	return nil
 }
 
-func (g *Instance) Start() error {
-	config := g.config
-	if config.AccessLogType == LogType_File {
-		if err := InitAccessLogger(config.AccessLogPath); err != nil {
-			return err
+func (g *Instance) Handle(msg log.Message) {
+	switch msg := msg.(type) {
+	case *log.AccessMessage:
+		g.RLock()
+		defer g.RUnlock()
+		if g.accessLogger != nil {
+			g.accessLogger.Log(msg)
 		}
-	}
-
-	if config.ErrorLogType == LogType_None {
-		SetLogLevel(LogLevel_Disabled)
-	} else {
-		if config.ErrorLogType == LogType_File {
-			if err := InitErrorLogger(config.ErrorLogPath); err != nil {
-				return err
+	case *log.GeneralMessage:
+		if msg.Severity.SevererThan(g.config.ErrorLogLevel) {
+			g.RLock()
+			defer g.RUnlock()
+			if g.errorLogger != nil {
+				g.errorLogger.Log(msg)
 			}
 		}
-		SetLogLevel(config.ErrorLogLevel)
+	default:
+		// Swallow
 	}
-
-	return nil
 }
 
-func (*Instance) Close() {
-	streamLoggerInstance.Close()
-	accessLoggerInstance.Close()
+func (g *Instance) Close() {
+	g.Lock()
+	defer g.Unlock()
+
+	g.accessLogger.Close()
+	g.accessLogger = nil
+
+	g.errorLogger.Close()
+	g.errorLogger = nil
 }
 
 func FromSpace(space app.Space) *Instance {

+ 1 - 2
app/proxyman/inbound/always.go

@@ -3,7 +3,6 @@ package inbound
 import (
 	"context"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/app/proxyman/mux"
 	"v2ray.com/core/common/dice"
@@ -36,7 +35,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
 	}
 	for port := pr.From; port <= pr.To; port++ {
 		if nl.HasNetwork(net.Network_TCP) {
-			log.Trace(newError("creating tcp worker on ", address, ":", port).AtDebug())
+			newError("creating tcp worker on ", address, ":", port).AtDebug().WriteToLog()
 			worker := &tcpWorker{
 				address:      address,
 				port:         net.Port(port),

+ 3 - 4
app/proxyman/inbound/dynamic.go

@@ -5,7 +5,6 @@ import (
 	"sync"
 	"time"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/app/proxyman/mux"
 	"v2ray.com/core/common/dice"
@@ -92,7 +91,7 @@ func (h *DynamicInboundHandler) refresh() error {
 		port := h.allocatePort()
 		p, err := proxy.CreateInboundHandler(ctx, h.proxyConfig)
 		if err != nil {
-			log.Trace(newError("failed to create proxy instance").Base(err).AtWarning())
+			newError("failed to create proxy instance").Base(err).AtWarning().WriteToLog()
 			continue
 		}
 		nl := p.Network()
@@ -108,7 +107,7 @@ func (h *DynamicInboundHandler) refresh() error {
 				sniffers:     h.receiverConfig.DomainOverride,
 			}
 			if err := worker.Start(); err != nil {
-				log.Trace(newError("failed to create TCP worker").Base(err).AtWarning())
+				newError("failed to create TCP worker").Base(err).AtWarning().WriteToLog()
 				continue
 			}
 			workers = append(workers, worker)
@@ -124,7 +123,7 @@ func (h *DynamicInboundHandler) refresh() error {
 				dispatcher:   h.mux,
 			}
 			if err := worker.Start(); err != nil {
-				log.Trace(newError("failed to create UDP worker").Base(err).AtWarning())
+				newError("failed to create UDP worker").Base(err).AtWarning().WriteToLog()
 				continue
 			}
 			workers = append(workers, worker)

+ 3 - 4
app/proxyman/inbound/worker.go

@@ -8,7 +8,6 @@ import (
 	"time"
 
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/net"
@@ -45,7 +44,7 @@ func (w *tcpWorker) callback(conn internet.Connection) {
 	if w.recvOrigDest {
 		dest, err := tcp.GetOriginalDestination(conn)
 		if err != nil {
-			log.Trace(newError("failed to get original destination").Base(err))
+			newError("failed to get original destination").Base(err).WriteToLog()
 		}
 		if dest.IsValid() {
 			ctx = proxy.ContextWithOriginalTarget(ctx, dest)
@@ -60,7 +59,7 @@ func (w *tcpWorker) callback(conn internet.Connection) {
 		ctx = proxyman.ContextWithProtocolSniffers(ctx, w.sniffers)
 	}
 	if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
-		log.Trace(newError("connection ends").Base(err))
+		newError("connection ends").Base(err).WriteToLog()
 	}
 	cancel()
 	conn.Close()
@@ -247,7 +246,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
 			ctx = proxy.ContextWithSource(ctx, source)
 			ctx = proxy.ContextWithInboundEntryPoint(ctx, net.UDPDestination(w.address, w.port))
 			if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
-				log.Trace(newError("connection ends").Base(err))
+				newError("connection ends").Base(err).WriteToLog()
 			}
 			w.removeConn(id)
 			cancel()

+ 10 - 11
app/proxyman/mux/mux.go

@@ -10,7 +10,6 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/errors"
@@ -99,7 +98,7 @@ func NewClient(p proxy.Outbound, dialer proxy.Dialer, m *ClientManager) (*Client
 			if err != io.EOF && err != context.Canceled {
 				traceErr = traceErr.AtWarning()
 			}
-			log.Trace(traceErr)
+			traceErr.WriteToLog()
 		}
 	}()
 
@@ -159,14 +158,14 @@ func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
 	defer writer.Close()
 	defer s.Close()
 
-	log.Trace(newError("dispatching request to ", dest))
+	newError("dispatching request to ", dest).WriteToLog()
 	data, _ := s.input.ReadTimeout(time.Millisecond * 500)
 	if err := writer.WriteMultiBuffer(data); err != nil {
-		log.Trace(newError("failed to write first payload").Base(err))
+		newError("failed to write first payload").Base(err).WriteToLog()
 		return
 	}
 	if err := buf.Copy(s.input, writer); err != nil {
-		log.Trace(newError("failed to fetch all input").Base(err))
+		newError("failed to fetch all input").Base(err).WriteToLog()
 	}
 }
 
@@ -240,7 +239,7 @@ func (m *Client) fetchOutput() {
 		meta, err := ReadMetadata(reader)
 		if err != nil {
 			if errors.Cause(err) != io.EOF {
-				log.Trace(newError("failed to read metadata").Base(err))
+				newError("failed to read metadata").Base(err).WriteToLog()
 			}
 			break
 		}
@@ -255,12 +254,12 @@ func (m *Client) fetchOutput() {
 		case SessionStatusKeep:
 			err = m.handleStatusKeep(meta, reader)
 		default:
-			log.Trace(newError("unknown status: ", meta.SessionStatus).AtWarning())
+			newError("unknown status: ", meta.SessionStatus).AtWarning().WriteToLog()
 			return
 		}
 
 		if err != nil {
-			log.Trace(newError("failed to process data").Base(err))
+			newError("failed to process data").Base(err).WriteToLog()
 			return
 		}
 	}
@@ -309,7 +308,7 @@ type ServerWorker struct {
 func handle(ctx context.Context, s *Session, output buf.Writer) {
 	writer := NewResponseWriter(s.ID, output, s.transferType)
 	if err := buf.Copy(s.input, writer); err != nil {
-		log.Trace(newError("session ", s.ID, " ends: ").Base(err))
+		newError("session ", s.ID, " ends: ").Base(err).WriteToLog()
 	}
 	writer.Close()
 	s.Close()
@@ -323,7 +322,7 @@ func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.Bu
 }
 
 func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
-	log.Trace(newError("received request for ", meta.Target))
+	newError("received request for ", meta.Target).WriteToLog()
 	inboundRay, err := w.dispatcher.Dispatch(ctx, meta.Target)
 	if err != nil {
 		if meta.Option.Has(OptionData) {
@@ -408,7 +407,7 @@ func (w *ServerWorker) run(ctx context.Context) {
 			err := w.handleFrame(ctx, reader)
 			if err != nil {
 				if errors.Cause(err) != io.EOF {
-					log.Trace(newError("unexpected EOF").Base(err))
+					newError("unexpected EOF").Base(err).WriteToLog()
 					input.CloseError()
 				}
 				return

+ 4 - 5
app/proxyman/outbound/handler.go

@@ -6,7 +6,6 @@ import (
 	"time"
 
 	"v2ray.com/core/app"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/app/proxyman/mux"
 	"v2ray.com/core/common/buf"
@@ -77,14 +76,14 @@ func (h *Handler) Dispatch(ctx context.Context, outboundRay ray.OutboundRay) {
 	if h.mux != nil {
 		err := h.mux.Dispatch(ctx, outboundRay)
 		if err != nil {
-			log.Trace(newError("failed to process outbound traffic").Base(err))
+			newError("failed to process outbound traffic").Base(err).WriteToLog()
 			outboundRay.OutboundOutput().CloseError()
 		}
 	} else {
 		err := h.proxy.Process(ctx, outboundRay, h)
 		// Ensure outbound ray is properly closed.
 		if err != nil && errors.Cause(err) != io.EOF {
-			log.Trace(newError("failed to process outbound traffic").Base(err))
+			newError("failed to process outbound traffic").Base(err).WriteToLog()
 			outboundRay.OutboundOutput().CloseError()
 		} else {
 			outboundRay.OutboundOutput().Close()
@@ -100,14 +99,14 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn
 			tag := h.senderSettings.ProxySettings.Tag
 			handler := h.outboundManager.GetHandler(tag)
 			if handler != nil {
-				log.Trace(newError("proxying to ", tag).AtDebug())
+				newError("proxying to ", tag).AtDebug().WriteToLog()
 				ctx = proxy.ContextWithTarget(ctx, dest)
 				stream := ray.NewRay(ctx)
 				go handler.Dispatch(ctx, stream)
 				return NewConnection(stream), nil
 			}
 
-			log.Trace(newError("failed to get outbound handler with tag: ", tag).AtWarning())
+			newError("failed to get outbound handler with tag: ", tag).AtWarning().WriteToLog()
 		}
 
 		if h.senderSettings.Via != nil {

+ 1 - 2
app/router/router.go

@@ -7,7 +7,6 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dns"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/proxy"
@@ -64,7 +63,7 @@ func (r *ipResolver) Resolve() []net.Address {
 		return r.ip
 	}
 
-	log.Trace(newError("looking for IP for domain: ", r.domain))
+	newError("looking for IP for domain: ", r.domain).WriteToLog()
 	r.resolved = true
 	ips := r.dnsServer.Get(r.domain)
 	if len(ips) == 0 {

+ 14 - 0
common/errors/errors.go

@@ -96,6 +96,19 @@ func (v *Error) Path(path ...string) *Error {
 	return v
 }
 
+// String returns the string representation of this error.
+func (v *Error) String() string {
+	return v.Error()
+}
+
+// WriteToLog writes current error into log.
+func (v *Error) WriteToLog() {
+	log.Record(&log.GeneralMessage{
+		Severity: GetSeverity(v),
+		Content:  v,
+	})
+}
+
 // New returns a new error object with message formed from given arguments.
 func New(msg ...interface{}) *Error {
 	return &Error{
@@ -119,6 +132,7 @@ func Cause(err error) error {
 	return err
 }
 
+// GetSeverity returns the actual severity of the error, including inner errors.
 func GetSeverity(err error) log.Severity {
 	if s, ok := err.(hasSeverity); ok {
 		return s.Severity()

+ 10 - 0
common/log/access.go

@@ -1,5 +1,11 @@
 package log
 
+import (
+	"strings"
+
+	"v2ray.com/core/common/serial"
+)
+
 type AccessStatus string
 
 const (
@@ -13,3 +19,7 @@ type AccessMessage struct {
 	Status AccessStatus
 	Reason interface{}
 }
+
+func (m *AccessMessage) String() string {
+	return strings.Join([]string{serial.ToString(m.From), string(m.Status), serial.ToString(m.To), serial.ToString(m.Reason)}, " ")
+}

+ 4 - 0
common/log/log.go

@@ -28,6 +28,10 @@ func (m *GeneralMessage) String() string {
 	return serial.Concat("[", m.Severity, "]: ", m.Content)
 }
 
+func (s Severity) SevererThan(another Severity) bool {
+	return s <= another
+}
+
 func Record(msg Message) {
 	h := (*Handler)(atomic.LoadPointer(&logHandler))
 	(*h).Handle(msg)

+ 2 - 3
common/net/address.go

@@ -4,7 +4,6 @@ import (
 	"net"
 	"strings"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/predicate"
 )
 
@@ -36,7 +35,7 @@ const (
 	AddressFamilyDomain = AddressFamily(2)
 )
 
-// Either returns true if current AddressFamily matches any of the AddressFamilys provided.
+// Either returns true if current AddressFamily matches any of the AddressFamilies provided.
 func (af AddressFamily) Either(fs ...AddressFamily) bool {
 	for _, f := range fs {
 		if af == f {
@@ -106,7 +105,7 @@ func IPAddress(ip []byte) Address {
 		}
 		return addr
 	default:
-		log.Trace(newError("invalid IP format: ", ip).AtError())
+		newError("invalid IP format: ", ip).AtError().WriteToLog()
 		return nil
 	}
 }

+ 1 - 2
plugin_linux.go

@@ -8,7 +8,6 @@ import (
 	"plugin"
 	"strings"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/platform"
 )
 
@@ -38,7 +37,7 @@ func loadPluginsInternal() error {
 			}
 			if gmf, ok := f.(GetMetadataFunc); ok {
 				metadata := gmf()
-				log.Trace(newError("plugin (", metadata.Name, ") loaded."))
+				newError("plugin (", metadata.Name, ") loaded.").WriteToLog()
 			}
 		}
 	}

+ 1 - 2
proxy/dokodemo/dokodemo.go

@@ -7,7 +7,6 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
@@ -57,7 +56,7 @@ func (d *DokodemoDoor) Network() net.NetworkList {
 }
 
 func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher dispatcher.Interface) error {
-	log.Trace(newError("processing connection from: ", conn.RemoteAddr()).AtDebug())
+	newError("processing connection from: ", conn.RemoteAddr()).AtDebug().WriteToLog()
 	dest := net.Destination{
 		Network: network,
 		Address: d.address,

+ 2 - 3
proxy/freedom/freedom.go

@@ -7,7 +7,6 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dns"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
@@ -87,7 +86,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 			Port:    net.Port(server.Port),
 		}
 	}
-	log.Trace(newError("opening connection to ", destination))
+	newError("opening connection to ", destination).WriteToLog()
 
 	input := outboundRay.OutboundInput()
 	output := outboundRay.OutboundOutput()
@@ -100,7 +99,7 @@ func (h *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 				Address: ip,
 				Port:    destination.Port,
 			}
-			log.Trace(newError("changing destination to ", destination))
+			newError("changing destination to ", destination).WriteToLog()
 		}
 	}
 

+ 8 - 4
proxy/http/server.go

@@ -12,11 +12,11 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/errors"
+	"v2ray.com/core/common/log"
 	"v2ray.com/core/common/net"
 	http_proto "v2ray.com/core/common/protocol/http"
 	"v2ray.com/core/common/signal"
@@ -127,7 +127,7 @@ Start:
 		}
 	}
 
-	log.Trace(newError("request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]"))
+	newError("request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]").WriteToLog()
 	conn.SetReadDeadline(time.Time{})
 
 	defaultPort := net.Port(80)
@@ -142,7 +142,11 @@ Start:
 	if err != nil {
 		return newError("malformed proxy host: ", host).AtWarning().Base(err)
 	}
-	log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "")
+	log.Record(&log.AccessMessage{
+		From:   conn.RemoteAddr(),
+		To:     request.URL,
+		Status: log.AccessAccepted,
+	})
 
 	if strings.ToUpper(request.Method) == "CONNECT" {
 		return s.handleConnect(ctx, request, reader, conn, dest, dispatcher)
@@ -278,7 +282,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
 				result = nil
 			}
 		} else {
-			log.Trace(newError("failed to read response from ", request.Host).Base(err).AtWarning())
+			newError("failed to read response from ", request.Host).Base(err).AtWarning().WriteToLog()
 			response = &http.Response{
 				Status:        "Service Unavailable",
 				StatusCode:    503,

+ 1 - 2
proxy/shadowsocks/client.go

@@ -4,7 +4,6 @@ import (
 	"context"
 
 	"v2ray.com/core/app"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
@@ -77,7 +76,7 @@ func (v *Client) Process(ctx context.Context, outboundRay ray.OutboundRay, diale
 	if err != nil {
 		return newError("failed to find an available destination").AtWarning().Base(err)
 	}
-	log.Trace(newError("tunneling request to ", destination, " via ", server.Destination()))
+	newError("tunneling request to ", destination, " via ", server.Destination()).WriteToLog()
 
 	defer conn.Close()
 

+ 31 - 11
proxy/shadowsocks/server.go

@@ -6,10 +6,10 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
+	"v2ray.com/core/common/log"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/common/signal"
@@ -94,30 +94,40 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 			request, data, err := DecodeUDPPacket(s.user, payload)
 			if err != nil {
 				if source, ok := proxy.SourceFromContext(ctx); ok {
-					log.Trace(newError("dropping invalid UDP packet from: ", source).Base(err))
-					log.Access(source, "", log.AccessRejected, err)
+					newError("dropping invalid UDP packet from: ", source).Base(err).WriteToLog()
+					log.Record(&log.AccessMessage{
+						From:   source,
+						To:     "",
+						Status: log.AccessRejected,
+						Reason: err,
+					})
 				}
 				payload.Release()
 				continue
 			}
 
 			if request.Option.Has(RequestOptionOneTimeAuth) && s.account.OneTimeAuth == Account_Disabled {
-				log.Trace(newError("client payload enables OTA but server doesn't allow it"))
+				newError("client payload enables OTA but server doesn't allow it").WriteToLog()
 				payload.Release()
 				continue
 			}
 
 			if !request.Option.Has(RequestOptionOneTimeAuth) && s.account.OneTimeAuth == Account_Enabled {
-				log.Trace(newError("client payload disables OTA but server forces it"))
+				newError("client payload disables OTA but server forces it").WriteToLog()
 				payload.Release()
 				continue
 			}
 
 			dest := request.Destination()
 			if source, ok := proxy.SourceFromContext(ctx); ok {
-				log.Access(source, dest, log.AccessAccepted, "")
+				log.Record(&log.AccessMessage{
+					From:   source,
+					To:     dest,
+					Status: log.AccessAccepted,
+					Reason: "",
+				})
 			}
-			log.Trace(newError("tunnelling request to ", dest))
+			newError("tunnelling request to ", dest).WriteToLog()
 
 			ctx = protocol.ContextWithUser(ctx, request.User)
 			udpServer.Dispatch(ctx, dest, data, func(payload *buf.Buffer) {
@@ -125,7 +135,7 @@ func (s *Server) handlerUDPPayload(ctx context.Context, conn internet.Connection
 
 				data, err := EncodeUDPPacket(request, payload.Bytes())
 				if err != nil {
-					log.Trace(newError("failed to encode UDP packet").Base(err).AtWarning())
+					newError("failed to encode UDP packet").Base(err).AtWarning().WriteToLog()
 					return
 				}
 				defer data.Release()
@@ -144,7 +154,12 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 	bufferedReader := buf.NewBufferedReader(buf.NewReader(conn))
 	request, bodyReader, err := ReadTCPSession(s.user, bufferedReader)
 	if err != nil {
-		log.Access(conn.RemoteAddr(), "", log.AccessRejected, err)
+		log.Record(&log.AccessMessage{
+			From:   conn.RemoteAddr(),
+			To:     "",
+			Status: log.AccessRejected,
+			Reason: err,
+		})
 		return newError("failed to create request from: ", conn.RemoteAddr()).Base(err)
 	}
 	conn.SetReadDeadline(time.Time{})
@@ -152,8 +167,13 @@ func (s *Server) handleConnection(ctx context.Context, conn internet.Connection,
 	bufferedReader.SetBuffered(false)
 
 	dest := request.Destination()
-	log.Access(conn.RemoteAddr(), dest, log.AccessAccepted, "")
-	log.Trace(newError("tunnelling request to ", dest))
+	log.Record(&log.AccessMessage{
+		From:   conn.RemoteAddr(),
+		To:     dest,
+		Status: log.AccessAccepted,
+		Reason: "",
+	})
+	newError("tunnelling request to ", dest).WriteToLog()
 
 	ctx = protocol.ContextWithUser(ctx, request.User)
 

+ 25 - 10
proxy/socks/server.go

@@ -7,10 +7,10 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
+	"v2ray.com/core/common/log"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/common/signal"
@@ -85,7 +85,12 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa
 	request, err := session.Handshake(reader, conn)
 	if err != nil {
 		if source, ok := proxy.SourceFromContext(ctx); ok {
-			log.Access(source, "", log.AccessRejected, err)
+			log.Record(&log.AccessMessage{
+				From:   source,
+				To:     "",
+				Status: log.AccessRejected,
+				Reason: err,
+			})
 		}
 		return newError("failed to read request").Base(err)
 	}
@@ -93,9 +98,14 @@ func (s *Server) processTCP(ctx context.Context, conn internet.Connection, dispa
 
 	if request.Command == protocol.RequestCommandTCP {
 		dest := request.Destination()
-		log.Trace(newError("TCP Connect request to ", dest))
+		newError("TCP Connect request to ", dest).WriteToLog()
 		if source, ok := proxy.SourceFromContext(ctx); ok {
-			log.Access(source, dest, log.AccessAccepted, "")
+			log.Record(&log.AccessMessage{
+				From:   source,
+				To:     dest,
+				Status: log.AccessAccepted,
+				Reason: "",
+			})
 		}
 
 		return s.transport(ctx, reader, conn, dest, dispatcher)
@@ -160,7 +170,7 @@ func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
 	udpServer := udp.NewDispatcher(dispatcher)
 
 	if source, ok := proxy.SourceFromContext(ctx); ok {
-		log.Trace(newError("client UDP connection from ", source))
+		newError("client UDP connection from ", source).WriteToLog()
 	}
 
 	reader := buf.NewReader(conn)
@@ -174,7 +184,7 @@ func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
 			request, data, err := DecodeUDPPacket(payload.Bytes())
 
 			if err != nil {
-				log.Trace(newError("failed to parse UDP request").Base(err))
+				newError("failed to parse UDP request").Base(err).WriteToLog()
 				continue
 			}
 
@@ -182,9 +192,14 @@ func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
 				continue
 			}
 
-			log.Trace(newError("send packet to ", request.Destination(), " with ", len(data), " bytes").AtDebug())
+			newError("send packet to ", request.Destination(), " with ", len(data), " bytes").AtDebug().WriteToLog()
 			if source, ok := proxy.SourceFromContext(ctx); ok {
-				log.Access(source, request.Destination, log.AccessAccepted, "")
+				log.Record(&log.AccessMessage{
+					From:   source,
+					To:     request.Destination,
+					Status: log.AccessAccepted,
+					Reason: "",
+				})
 			}
 
 			dataBuf := buf.New()
@@ -192,12 +207,12 @@ func (v *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
 			udpServer.Dispatch(ctx, request.Destination(), dataBuf, func(payload *buf.Buffer) {
 				defer payload.Release()
 
-				log.Trace(newError("writing back UDP response with ", payload.Len(), " bytes").AtDebug())
+				newError("writing back UDP response with ", payload.Len(), " bytes").AtDebug().WriteToLog()
 
 				udpMessage, err := EncodeUDPPacket(request, payload.Bytes())
 				defer udpMessage.Release()
 				if err != nil {
-					log.Trace(newError("failed to write UDP response").AtWarning().Base(err))
+					newError("failed to write UDP response").AtWarning().Base(err).WriteToLog()
 				}
 
 				conn.Write(udpMessage.Bytes())

+ 1 - 2
proxy/vmess/account.go

@@ -1,7 +1,6 @@
 package vmess
 
 import (
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/dice"
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/common/uuid"
@@ -32,7 +31,7 @@ func (a *InternalAccount) Equals(account protocol.Account) bool {
 func (a *Account) AsAccount() (protocol.Account, error) {
 	id, err := uuid.ParseString(a.Id)
 	if err != nil {
-		log.Trace(newError("failed to parse ID").Base(err).AtError())
+		newError("failed to parse ID").Base(err).AtError().WriteToLog()
 		return nil, err
 	}
 	protoID := protocol.NewID(id)

+ 3 - 4
proxy/vmess/encoding/client.go

@@ -10,7 +10,6 @@ import (
 
 	"golang.org/x/crypto/chacha20poly1305"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/bitmask"
 	"v2ray.com/core/common/buf"
@@ -64,7 +63,7 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
 	timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)()
 	account, err := header.User.GetTypedAccount()
 	if err != nil {
-		log.Trace(newError("failed to get user account: ", err).AtError())
+		newError("failed to get user account: ", err).AtError().WriteToLog()
 		return nil
 	}
 	idHash := c.idHash(account.(*vmess.InternalAccount).AnyValidID().Bytes())
@@ -201,7 +200,7 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
 	defer buffer.Release()
 
 	if err := buffer.AppendSupplier(buf.ReadFullFrom(c.responseReader, 4)); err != nil {
-		log.Trace(newError("failed to read response header").Base(err))
+		newError("failed to read response header").Base(err).WriteToLog()
 		return nil, err
 	}
 
@@ -218,7 +217,7 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
 		dataLen := int(buffer.Byte(3))
 
 		if err := buffer.Reset(buf.ReadFullFrom(c.responseReader, dataLen)); err != nil {
-			log.Trace(newError("failed to read response command").Base(err))
+			newError("failed to read response command").Base(err).WriteToLog()
 			return nil, err
 		}
 		command, err := UnmarshalCommand(cmdID, buffer.Bytes())

+ 19 - 8
proxy/vmess/inbound/inbound.go

@@ -10,12 +10,12 @@ import (
 
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/errors"
+	"v2ray.com/core/common/log"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/protocol"
 	"v2ray.com/core/common/serial"
@@ -192,8 +192,13 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
 
 	if err != nil {
 		if errors.Cause(err) != io.EOF {
-			log.Access(connection.RemoteAddr(), "", log.AccessRejected, err)
-			log.Trace(newError("invalid request from ", connection.RemoteAddr(), ": ", err).AtInfo())
+			log.Record(&log.AccessMessage{
+				From:   connection.RemoteAddr(),
+				To:     "",
+				Status: log.AccessRejected,
+				Reason: err,
+			})
+			newError("invalid request from ", connection.RemoteAddr(), ": ", err).AtInfo().WriteToLog()
 		}
 		return err
 	}
@@ -203,11 +208,17 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
 		request.Port = net.Port(0)
 	}
 
-	log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, "")
-	log.Trace(newError("received request for ", request.Destination()))
+	log.Record(&log.AccessMessage{
+		From:   connection.RemoteAddr(),
+		To:     request.Destination(),
+		Status: log.AccessAccepted,
+		Reason: "",
+	})
+
+	newError("received request for ", request.Destination()).WriteToLog()
 
 	if err := connection.SetReadDeadline(time.Time{}); err != nil {
-		log.Trace(newError("unable to set back read deadline").Base(err))
+		newError("unable to set back read deadline").Base(err).WriteToLog()
 	}
 
 	sessionPolicy = h.policyManager.GetPolicy(request.User.Level)
@@ -254,7 +265,7 @@ func (h *Handler) generateCommand(ctx context.Context, request *protocol.Request
 		if h.inboundHandlerManager != nil {
 			handler, err := h.inboundHandlerManager.GetHandler(ctx, tag)
 			if err != nil {
-				log.Trace(newError("failed to get detour handler: ", tag, err).AtWarning())
+				newError("failed to get detour handler: ", tag, err).AtWarning().WriteToLog()
 				return nil
 			}
 			proxyHandler, port, availableMin := handler.GetRandomInboundProxy()
@@ -264,7 +275,7 @@ func (h *Handler) generateCommand(ctx context.Context, request *protocol.Request
 					availableMin = 255
 				}
 
-				log.Trace(newError("pick detour handler for port ", port, " for ", availableMin, " minutes.").AtDebug())
+				newError("pick detour handler for port ", port, " for ", availableMin, " minutes.").AtDebug().WriteToLog()
 				user := inboundHandler.GetUser(request.User.Email)
 				if user == nil {
 					return nil

+ 1 - 2
proxy/vmess/outbound/outbound.go

@@ -7,7 +7,6 @@ import (
 	"time"
 
 	"v2ray.com/core/app"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
@@ -80,7 +79,7 @@ func (v *Handler) Process(ctx context.Context, outboundRay ray.OutboundRay, dial
 	if !ok {
 		return newError("target not specified").AtError()
 	}
-	log.Trace(newError("tunneling request to ", target, " via ", rec.Destination()))
+	newError("tunneling request to ", target, " via ", rec.Destination()).WriteToLog()
 
 	command := protocol.RequestCommandTCP
 	if target.Network == net.Network_UDP {

+ 9 - 4
testing/scenarios/common.go

@@ -1,7 +1,6 @@
 package scenarios
 
 import (
-	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -14,8 +13,8 @@ import (
 
 	"github.com/golang/protobuf/proto"
 	"v2ray.com/core"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
+	"v2ray.com/core/common/log"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/retry"
 )
@@ -114,12 +113,18 @@ func GetSourcePath() string {
 }
 
 func CloseAllServers(servers []*exec.Cmd) {
-	log.Trace(errors.New("Closing all servers."))
+	log.Record(&log.GeneralMessage{
+		Severity: log.Severity_Info,
+		Content:  "Closing all servers.",
+	})
 	for _, server := range servers {
 		server.Process.Signal(os.Interrupt)
 	}
 	for _, server := range servers {
 		server.Process.Wait()
 	}
-	log.Trace(errors.New("All server closed."))
+	log.Record(&log.GeneralMessage{
+		Severity: log.Severity_Info,
+		Content:  "All server closed.",
+	})
 }

+ 5 - 6
transport/internet/kcp/connection.go

@@ -7,7 +7,6 @@ import (
 	"sync/atomic"
 	"time"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/predicate"
 )
@@ -201,7 +200,7 @@ type Connection struct {
 
 // NewConnection create a new KCP connection between local and remote.
 func NewConnection(meta ConnMetadata, writer PacketWriter, closer io.Closer, config *Config) *Connection {
-	log.Trace(newError("creating connection ", meta.Conversation))
+	newError("creating connection ", meta.Conversation).WriteToLog()
 
 	conn := &Connection{
 		meta:       meta,
@@ -404,7 +403,7 @@ func (v *Connection) SetState(state State) {
 	current := v.Elapsed()
 	atomic.StoreInt32((*int32)(&v.state), int32(state))
 	atomic.StoreUint32(&v.stateBeginTime, current)
-	log.Trace(newError("#", v.meta.Conversation, " entering state ", state, " at ", current).AtDebug())
+	newError("#", v.meta.Conversation, " entering state ", state, " at ", current).AtDebug().WriteToLog()
 
 	switch state {
 	case StateReadyToClose:
@@ -441,7 +440,7 @@ func (v *Connection) Close() error {
 	if state.Is(StateReadyToClose, StateTerminating, StateTerminated) {
 		return ErrClosedConnection
 	}
-	log.Trace(newError("closing connection to ", v.meta.RemoteAddr))
+	newError("closing connection to ", v.meta.RemoteAddr).WriteToLog()
 
 	if state == StateActive {
 		v.SetState(StateReadyToClose)
@@ -510,7 +509,7 @@ func (v *Connection) Terminate() {
 	if v == nil {
 		return
 	}
-	log.Trace(newError("terminating connection to ", v.RemoteAddr()))
+	newError("terminating connection to ", v.RemoteAddr()).WriteToLog()
 
 	//v.SetState(StateTerminated)
 	v.OnDataInput()
@@ -600,7 +599,7 @@ func (v *Connection) flush() {
 	}
 
 	if v.State() == StateTerminating {
-		log.Trace(newError("#", v.meta.Conversation, " sending terminating cmd.").AtDebug())
+		newError("#", v.meta.Conversation, " sending terminating cmd.").AtDebug().WriteToLog()
 		v.Ping(current, CommandTerminate)
 
 		if current-atomic.LoadUint32(&v.stateBeginTime) > 8000 {

+ 1 - 2
transport/internet/kcp/dialer.go

@@ -6,7 +6,6 @@ import (
 	"io"
 	"sync/atomic"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/dice"
@@ -38,7 +37,7 @@ func fetchInput(ctx context.Context, input io.Reader, reader PacketReader, conn
 
 func DialKCP(ctx context.Context, dest net.Destination) (internet.Connection, error) {
 	dest.Network = net.Network_UDP
-	log.Trace(newError("dialing mKCP to ", dest))
+	newError("dialing mKCP to ", dest).WriteToLog()
 
 	src := internet.DialerSourceFromContext(ctx)
 	rawConn, err := internet.DialSystem(ctx, src, dest)

+ 2 - 3
transport/internet/kcp/listener.go

@@ -6,7 +6,6 @@ import (
 	"crypto/tls"
 	"sync"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/net"
@@ -71,7 +70,7 @@ func NewListener(ctx context.Context, address net.Address, port net.Port, addCon
 	l.Lock()
 	l.hub = hub
 	l.Unlock()
-	log.Trace(newError("listening on ", address, ":", port))
+	newError("listening on ", address, ":", port).WriteToLog()
 	return l, nil
 }
 
@@ -80,7 +79,7 @@ func (v *Listener) OnReceive(payload *buf.Buffer, src net.Destination, originalD
 
 	segments := v.reader.Read(payload.Bytes())
 	if len(segments) == 0 {
-		log.Trace(newError("discarding invalid payload from ", src))
+		newError("discarding invalid payload from ", src).WriteToLog()
 		return
 	}
 

+ 1 - 2
transport/internet/tcp/dialer.go

@@ -3,7 +3,6 @@ package tcp
 import (
 	"context"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
@@ -19,7 +18,7 @@ func getTCPSettingsFromContext(ctx context.Context) *Config {
 }
 
 func Dial(ctx context.Context, dest net.Destination) (internet.Connection, error) {
-	log.Trace(newError("dialing TCP to ", dest))
+	newError("dialing TCP to ", dest).WriteToLog()
 	src := internet.DialerSourceFromContext(ctx)
 
 	conn, err := internet.DialSystem(ctx, src, dest)

+ 2 - 3
transport/internet/tcp/hub.go

@@ -4,7 +4,6 @@ import (
 	"context"
 	gotls "crypto/tls"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/retry"
@@ -28,7 +27,7 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, addConn
 	if err != nil {
 		return nil, err
 	}
-	log.Trace(newError("listening TCP on ", address, ":", port))
+	newError("listening TCP on ", address, ":", port).WriteToLog()
 	networkSettings := internet.TransportSettingsFromContext(ctx)
 	tcpSettings := networkSettings.(*Config)
 
@@ -74,7 +73,7 @@ func (v *TCPListener) KeepAccepting(ctx context.Context) {
 			return nil
 		})
 		if err != nil {
-			log.Trace(newError("failed to accepted raw connections").Base(err).AtWarning())
+			newError("failed to accepted raw connections").Base(err).AtWarning().WriteToLog()
 			continue
 		}
 

+ 1 - 2
transport/internet/tcp/sockopt_linux.go

@@ -5,7 +5,6 @@ package tcp
 import (
 	"syscall"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
 )
@@ -25,7 +24,7 @@ func GetOriginalDestination(conn internet.Connection) (net.Destination, error) {
 	err = rawConn.Control(func(fd uintptr) {
 		addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST)
 		if err != nil {
-			log.Trace(newError("failed to call getsockopt").Base(err))
+			newError("failed to call getsockopt").Base(err).WriteToLog()
 			return
 		}
 		ip := net.IPAddress(addr.Multiaddr[4:8])

+ 1 - 2
transport/internet/tls/config.go

@@ -4,7 +4,6 @@ import (
 	"context"
 	"crypto/tls"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
 )
@@ -18,7 +17,7 @@ func (c *Config) BuildCertificates() []tls.Certificate {
 	for _, entry := range c.Certificate {
 		keyPair, err := tls.X509KeyPair(entry.Certificate, entry.Key)
 		if err != nil {
-			log.Trace(newError("ignoring invalid X509 key pair").Base(err).AtWarning())
+			newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
 			continue
 		}
 		certs = append(certs, keyPair)

+ 4 - 5
transport/internet/udp/dispatcher.go

@@ -6,7 +6,6 @@ import (
 	"time"
 
 	"v2ray.com/core/app/dispatcher"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/common/signal"
@@ -52,7 +51,7 @@ func (v *Dispatcher) getInboundRay(dest net.Destination, callback ResponseCallba
 		return entry
 	}
 
-	log.Trace(newError("establishing new connection for ", dest))
+	newError("establishing new connection for ", dest).WriteToLog()
 
 	ctx, cancel := context.WithCancel(context.Background())
 	removeRay := func() {
@@ -73,13 +72,13 @@ func (v *Dispatcher) getInboundRay(dest net.Destination, callback ResponseCallba
 
 func (v *Dispatcher) Dispatch(ctx context.Context, destination net.Destination, payload *buf.Buffer, callback ResponseCallback) {
 	// TODO: Add user to destString
-	log.Trace(newError("dispatch request to: ", destination).AtDebug())
+	newError("dispatch request to: ", destination).AtDebug().WriteToLog()
 
 	conn := v.getInboundRay(destination, callback)
 	outputStream := conn.inbound.InboundInput()
 	if outputStream != nil {
 		if err := outputStream.WriteMultiBuffer(buf.NewMultiBufferValue(payload)); err != nil {
-			log.Trace(newError("failed to write first UDP payload").Base(err))
+			newError("failed to write first UDP payload").Base(err).WriteToLog()
 			conn.cancel()
 			return
 		}
@@ -99,7 +98,7 @@ func handleInput(ctx context.Context, conn *connEntry, callback ResponseCallback
 
 		mb, err := input.ReadMultiBuffer()
 		if err != nil {
-			log.Trace(newError("failed to handle UDP input").Base(err))
+			newError("failed to handle UDP input").Base(err).WriteToLog()
 			conn.cancel()
 			return
 		}

+ 3 - 4
transport/internet/udp/hub.go

@@ -3,7 +3,6 @@ package udp
 import (
 	"context"
 
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/dice"
 	"v2ray.com/core/common/net"
@@ -91,7 +90,7 @@ func ListenUDP(address net.Address, port net.Port, option ListenOption) (*Hub, e
 	if err != nil {
 		return nil, err
 	}
-	log.Trace(newError("listening UDP on ", address, ":", port))
+	newError("listening UDP on ", address, ":", port).WriteToLog()
 	if option.ReceiveOriginalDest {
 		rawConn, err := udpConn.SyscallConn()
 		if err != nil {
@@ -99,7 +98,7 @@ func ListenUDP(address net.Address, port net.Port, option ListenOption) (*Hub, e
 		}
 		err = rawConn.Control(func(fd uintptr) {
 			if err := SetOriginalDestOptions(int(fd)); err != nil {
-				log.Trace(newError("failed to set socket options").Base(err))
+				newError("failed to set socket options").Base(err).WriteToLog()
 			}
 		})
 		if err != nil {
@@ -150,7 +149,7 @@ L:
 		})
 
 		if err != nil {
-			log.Trace(newError("failed to read UDP msg").Base(err))
+			newError("failed to read UDP msg").Base(err).WriteToLog()
 			buffer.Release()
 			continue
 		}

+ 1 - 2
transport/internet/websocket/dialer.go

@@ -5,7 +5,6 @@ import (
 	"time"
 
 	"github.com/gorilla/websocket"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	"v2ray.com/core/transport/internet"
@@ -14,7 +13,7 @@ import (
 
 // Dial dials a WebSocket connection to the given destination.
 func Dial(ctx context.Context, dest net.Destination) (internet.Connection, error) {
-	log.Trace(newError("creating connection to ", dest))
+	newError("creating connection to ", dest).WriteToLog()
 
 	conn, err := dialWebsocket(ctx, dest)
 	if err != nil {

+ 2 - 3
transport/internet/websocket/hub.go

@@ -9,7 +9,6 @@ import (
 	"time"
 
 	"github.com/gorilla/websocket"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/net"
 	http_proto "v2ray.com/core/common/protocol/http"
@@ -35,7 +34,7 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
 	}
 	conn, err := upgrader.Upgrade(writer, request, nil)
 	if err != nil {
-		log.Trace(newError("failed to convert to WebSocket connection").Base(err))
+		newError("failed to convert to WebSocket connection").Base(err).WriteToLog()
 		return
 	}
 
@@ -99,7 +98,7 @@ func (ln *Listener) listenws(address net.Address, port net.Port) error {
 			ln:   ln,
 		})
 		if err != nil {
-			log.Trace(newError("failed to serve http for WebSocket").Base(err).AtWarning())
+			newError("failed to serve http for WebSocket").Base(err).AtWarning().WriteToLog()
 		}
 	}()
 

+ 1 - 14
v2ray.go

@@ -6,7 +6,6 @@ import (
 	"v2ray.com/core/app"
 	"v2ray.com/core/app/dispatcher"
 	"v2ray.com/core/app/dns"
-	"v2ray.com/core/app/log"
 	"v2ray.com/core/app/policy"
 	"v2ray.com/core/app/proxyman"
 	"v2ray.com/core/common"
@@ -61,18 +60,6 @@ func newSimpleServer(config *Config) (*simpleServer, error) {
 		}
 	}
 
-	if log.FromSpace(space) == nil {
-		l, err := app.CreateAppFromConfig(ctx, &log.Config{
-			ErrorLogType:  log.LogType_Console,
-			ErrorLogLevel: log.LogLevel_Warning,
-			AccessLogType: log.LogType_None,
-		})
-		if err != nil {
-			return nil, newError("failed apply default log settings").Base(err)
-		}
-		common.Must(space.AddApplication(l))
-	}
-
 	outboundHandlerManager := proxyman.OutboundHandlerManagerFromSpace(space)
 	if outboundHandlerManager == nil {
 		o, err := app.CreateAppFromConfig(ctx, new(proxyman.OutboundConfig))
@@ -163,7 +150,7 @@ func (s *simpleServer) Start() error {
 	if err := s.space.Start(); err != nil {
 		return err
 	}
-	log.Trace(newError("V2Ray started").AtWarning())
+	newError("V2Ray started").AtWarning().WriteToLog()
 
 	return nil
 }