improving logger to write to a file
This commit is contained in:
		
							
								
								
									
										56
									
								
								client.go
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								client.go
									
									
									
									
									
								
							@ -721,36 +721,53 @@ func (cts *ClientConn) AddClientRoutes(peer_addrs []string) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for _, v = range peer_addrs {
 | 
						for _, v = range peer_addrs {
 | 
				
			||||||
		va = strings.Split(v, ",")
 | 
							va = strings.Split(v, ",")
 | 
				
			||||||
		if len(va) <= 0 || len(va) >= 4 {
 | 
							if len(va) <= 0 { return fmt.Errorf("blank value") }
 | 
				
			||||||
			return fmt.Errorf("invalid address %v", va)
 | 
							if len(va) >= 5 { return fmt.Errorf("too many fields in %v", v) }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_, port, err = net.SplitHostPort(va[0])
 | 
							_, port, err = net.SplitHostPort(strings.TrimSpace(va[0]))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return fmt.Errorf("invalid address %s", va[0], err.Error())
 | 
								return fmt.Errorf("invalid address %s", va[0], err.Error())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if len(va) >= 2 {
 | 
							if len(va) >= 2 {
 | 
				
			||||||
			_, _, err = net.SplitHostPort(va[1])
 | 
								var f string
 | 
				
			||||||
 | 
								f = strings.TrimSpace(va[1])
 | 
				
			||||||
 | 
								_, _, err = net.SplitHostPort(f)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return fmt.Errorf("invalid address %s", va[1], err.Error())
 | 
									return fmt.Errorf("invalid address %s", va[1], err.Error())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			svc_addr = va[1]
 | 
								svc_addr = f
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if len(va) >= 3 {
 | 
					 | 
				
			||||||
			ptc_name = va[2]
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		option = RouteOption(ROUTE_OPTION_TCP)
 | 
							option = RouteOption(ROUTE_OPTION_TCP)
 | 
				
			||||||
		// automatic determination of protocol for common ports
 | 
							if len(va) >= 3 {
 | 
				
			||||||
		switch port {
 | 
								switch strings.ToLower(strings.TrimSpace(va[2])) {
 | 
				
			||||||
			case "22":
 | 
									case "ssh":
 | 
				
			||||||
				option |= RouteOption(ROUTE_OPTION_SSH)
 | 
										option |= RouteOption(ROUTE_OPTION_SSH)
 | 
				
			||||||
			case "80":
 | 
									case "http":
 | 
				
			||||||
				option |= RouteOption(ROUTE_OPTION_HTTP)
 | 
										option |= RouteOption(ROUTE_OPTION_HTTP)
 | 
				
			||||||
			case "443":
 | 
									case "https":
 | 
				
			||||||
				option |= RouteOption(ROUTE_OPTION_HTTPS)
 | 
										option |= RouteOption(ROUTE_OPTION_HTTPS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									case "":
 | 
				
			||||||
 | 
										fallthrough
 | 
				
			||||||
 | 
									case "auto":
 | 
				
			||||||
 | 
										// automatic determination of protocol for common ports
 | 
				
			||||||
 | 
										switch port {
 | 
				
			||||||
 | 
											case "22":
 | 
				
			||||||
 | 
												option |= RouteOption(ROUTE_OPTION_SSH)
 | 
				
			||||||
 | 
											case "80":
 | 
				
			||||||
 | 
												option |= RouteOption(ROUTE_OPTION_HTTP)
 | 
				
			||||||
 | 
											case "443":
 | 
				
			||||||
 | 
												option |= RouteOption(ROUTE_OPTION_HTTPS)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									default:
 | 
				
			||||||
 | 
										return fmt.Errorf("invalid option value %s", va[2])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if len(va) >= 4 {
 | 
				
			||||||
 | 
								ptc_name = strings.TrimSpace(va[3])
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_, err = cts.AddNewClientRoute(va[0], ptc_name, svc_addr, "", option)
 | 
							_, err = cts.AddNewClientRoute(va[0], ptc_name, svc_addr, "", option)
 | 
				
			||||||
@ -1460,6 +1477,9 @@ func (c *Client) StopServices() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Client) FixServices() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Client) WaitForTermination() {
 | 
					func (c *Client) WaitForTermination() {
 | 
				
			||||||
	c.wg.Wait()
 | 
						c.wg.Wait()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										81
									
								
								cmd/main.go
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								cmd/main.go
									
									
									
									
									
								
							@ -29,10 +29,30 @@ var hodul_tls_key_text []byte
 | 
				
			|||||||
// --------------------------------------------------------------------
 | 
					// --------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AppLogger struct {
 | 
					type AppLogger struct {
 | 
				
			||||||
	id string
 | 
						Id       string
 | 
				
			||||||
	out io.Writer
 | 
						Out      io.Writer
 | 
				
			||||||
	mtx sync.Mutex
 | 
						Mask     hodu.LogMask
 | 
				
			||||||
	mask hodu.LogMask
 | 
					
 | 
				
			||||||
 | 
						_mtx     sync.Mutex
 | 
				
			||||||
 | 
						_file    *os.File
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewAppLogger (id string, w io.Writer, mask hodu.LogMask) *AppLogger {
 | 
				
			||||||
 | 
						return &AppLogger{Id: id, Out: w, Mask: mask}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewAppLoggerToFile (id string, file string, mask hodu.LogMask) (*AppLogger, error) {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						var f *os.File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f, err = os.OpenFile(file, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
 | 
				
			||||||
 | 
						if err != nil { return nil, err }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &AppLogger{Id: id, Out: f, Mask: mask, _file: f}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l* AppLogger) Close() {
 | 
				
			||||||
 | 
						if l._file != nil { l._file.Close() }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (l* AppLogger) Write(id string, level hodu.LogLevel, fmtstr string, args ...interface{}) {
 | 
					func (l* AppLogger) Write(id string, level hodu.LogLevel, fmtstr string, args ...interface{}) {
 | 
				
			||||||
@ -47,7 +67,7 @@ func (l* AppLogger) Write(id string, level hodu.LogLevel, fmtstr string, args ..
 | 
				
			|||||||
	var caller_line int
 | 
						var caller_line int
 | 
				
			||||||
	var caller_ok bool
 | 
						var caller_ok bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if l.mask & hodu.LogMask(level) == 0 { return }
 | 
						if l.Mask & hodu.LogMask(level) == 0 { return }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	now = time.Now()
 | 
						now = time.Now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,20 +85,20 @@ func (l* AppLogger) Write(id string, level hodu.LogLevel, fmtstr string, args ..
 | 
				
			|||||||
// TODO: add pid?
 | 
					// TODO: add pid?
 | 
				
			||||||
	msg = fmt.Sprintf(fmtstr, args...)
 | 
						msg = fmt.Sprintf(fmtstr, args...)
 | 
				
			||||||
	if id == "" {
 | 
						if id == "" {
 | 
				
			||||||
		lid = fmt.Sprintf("%s: ", l.id)
 | 
							lid = fmt.Sprintf("%s: ", l.Id)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		lid = fmt.Sprintf("%s(%s): ", l.id, id)
 | 
							lid = fmt.Sprintf("%s(%s): ", l.Id, id)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l.mtx.Lock()
 | 
						l._mtx.Lock()
 | 
				
			||||||
	l.out.Write([]byte(hdr))
 | 
						l.Out.Write([]byte(hdr))
 | 
				
			||||||
	if caller_ok {
 | 
						if caller_ok {
 | 
				
			||||||
		l.out.Write([]byte(fmt.Sprintf("[%s:%d] ", filepath.Base(caller_file), caller_line)))
 | 
							l.Out.Write([]byte(fmt.Sprintf("[%s:%d] ", filepath.Base(caller_file), caller_line)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if lid != "" { l.out.Write([]byte(lid)) }
 | 
						if lid != "" { l.Out.Write([]byte(lid)) }
 | 
				
			||||||
	l.out.Write([]byte(msg))
 | 
						l.Out.Write([]byte(msg))
 | 
				
			||||||
	if msg[len(msg) - 1] != '\n' { l.out.Write([]byte("\n")) }
 | 
						if msg[len(msg) - 1] != '\n' { l.Out.Write([]byte("\n")) }
 | 
				
			||||||
	l.mtx.Unlock()
 | 
						l._mtx.Unlock()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// --------------------------------------------------------------------
 | 
					// --------------------------------------------------------------------
 | 
				
			||||||
@ -105,8 +125,8 @@ chan_loop:
 | 
				
			|||||||
	for {
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-sighup_chan:
 | 
							case <-sighup_chan:
 | 
				
			||||||
			// TODO:
 | 
								sh.svc.FixServices()
 | 
				
			||||||
			//sh.svc.ReqReload()
 | 
					
 | 
				
			||||||
		case sig = <-sigterm_chan:
 | 
							case sig = <-sigterm_chan:
 | 
				
			||||||
			sh.svc.StopServices()
 | 
								sh.svc.StopServices()
 | 
				
			||||||
			sh.svc.WriteLog ("", hodu.LOG_INFO, "Received %s signal", sig)
 | 
								sh.svc.WriteLog ("", hodu.LOG_INFO, "Received %s signal", sig)
 | 
				
			||||||
@ -132,6 +152,9 @@ func (sh *signal_handler) StopServices() {
 | 
				
			|||||||
	syscall.Kill(syscall.Getpid(), syscall.SIGTERM) // TODO: find a better to terminate the signal handler...
 | 
						syscall.Kill(syscall.Getpid(), syscall.SIGTERM) // TODO: find a better to terminate the signal handler...
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sh *signal_handler) FixServices() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (sh *signal_handler) WaitForTermination() {
 | 
					func (sh *signal_handler) WaitForTermination() {
 | 
				
			||||||
	// not implemented. see the comment in StartServices()
 | 
						// not implemented. see the comment in StartServices()
 | 
				
			||||||
	// sh.wg.Wait()
 | 
						// sh.wg.Wait()
 | 
				
			||||||
@ -151,6 +174,7 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, cfg
 | 
				
			|||||||
	var ctl_prefix string
 | 
						var ctl_prefix string
 | 
				
			||||||
	var logger *AppLogger
 | 
						var logger *AppLogger
 | 
				
			||||||
	var log_mask hodu.LogMask
 | 
						var log_mask hodu.LogMask
 | 
				
			||||||
 | 
						var log_file string
 | 
				
			||||||
	var max_rpc_conns int
 | 
						var max_rpc_conns int
 | 
				
			||||||
	var max_peers int
 | 
						var max_peers int
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
@ -179,6 +203,7 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, cfg
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		ctl_prefix = cfg.CTL.Service.Prefix
 | 
							ctl_prefix = cfg.CTL.Service.Prefix
 | 
				
			||||||
		log_mask = log_strings_to_mask(cfg.APP.LogMask)
 | 
							log_mask = log_strings_to_mask(cfg.APP.LogMask)
 | 
				
			||||||
 | 
							log_file = cfg.APP.LogFile
 | 
				
			||||||
		max_rpc_conns = cfg.APP.MaxRpcConns
 | 
							max_rpc_conns = cfg.APP.MaxRpcConns
 | 
				
			||||||
		max_peers = cfg.APP.MaxPeers
 | 
							max_peers = cfg.APP.MaxPeers
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -187,8 +212,15 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, cfg
 | 
				
			|||||||
		return fmt.Errorf("no rpc service addresses specified")
 | 
							return fmt.Errorf("no rpc service addresses specified")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: Change out field depending on cfg.APP.LogFile
 | 
						if log_file == "" {
 | 
				
			||||||
	logger = &AppLogger{id: "server", out: os.Stderr, mask: log_mask}
 | 
							logger = NewAppLogger("server", os.Stderr, log_mask)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							logger, err = NewAppLoggerToFile("server", log_file, log_mask)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("failed to initialize logger - %s", err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s, err = hodu.NewServer(
 | 
						s, err = hodu.NewServer(
 | 
				
			||||||
		context.Background(),
 | 
							context.Background(),
 | 
				
			||||||
		logger,
 | 
							logger,
 | 
				
			||||||
@ -210,6 +242,7 @@ func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, cfg
 | 
				
			|||||||
	s.StartPxyService()
 | 
						s.StartPxyService()
 | 
				
			||||||
	s.StartExtService(&signal_handler{svc:s}, nil)
 | 
						s.StartExtService(&signal_handler{svc:s}, nil)
 | 
				
			||||||
	s.WaitForTermination()
 | 
						s.WaitForTermination()
 | 
				
			||||||
 | 
						logger.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -224,6 +257,7 @@ func client_main(ctl_addrs []string, rpc_addrs []string, peer_addrs []string, cf
 | 
				
			|||||||
	var cc hodu.ClientConfig
 | 
						var cc hodu.ClientConfig
 | 
				
			||||||
	var logger *AppLogger
 | 
						var logger *AppLogger
 | 
				
			||||||
	var log_mask hodu.LogMask
 | 
						var log_mask hodu.LogMask
 | 
				
			||||||
 | 
						var log_file string
 | 
				
			||||||
	var max_rpc_conns int
 | 
						var max_rpc_conns int
 | 
				
			||||||
	var max_peers int
 | 
						var max_peers int
 | 
				
			||||||
	var peer_conn_tmout time.Duration
 | 
						var peer_conn_tmout time.Duration
 | 
				
			||||||
@ -247,6 +281,7 @@ func client_main(ctl_addrs []string, rpc_addrs []string, peer_addrs []string, cf
 | 
				
			|||||||
		cc.ServerSeedTmout = cfg.RPC.Endpoint.SeedTmout
 | 
							cc.ServerSeedTmout = cfg.RPC.Endpoint.SeedTmout
 | 
				
			||||||
		cc.ServerAuthority = cfg.RPC.Endpoint.Authority
 | 
							cc.ServerAuthority = cfg.RPC.Endpoint.Authority
 | 
				
			||||||
		log_mask = log_strings_to_mask(cfg.APP.LogMask)
 | 
							log_mask = log_strings_to_mask(cfg.APP.LogMask)
 | 
				
			||||||
 | 
							log_file = cfg.APP.LogFile
 | 
				
			||||||
		max_rpc_conns = cfg.APP.MaxRpcConns
 | 
							max_rpc_conns = cfg.APP.MaxRpcConns
 | 
				
			||||||
		max_peers = cfg.APP.MaxPeers
 | 
							max_peers = cfg.APP.MaxPeers
 | 
				
			||||||
		peer_conn_tmout = cfg.APP.PeerConnTmout
 | 
							peer_conn_tmout = cfg.APP.PeerConnTmout
 | 
				
			||||||
@ -257,7 +292,14 @@ func client_main(ctl_addrs []string, rpc_addrs []string, peer_addrs []string, cf
 | 
				
			|||||||
	cc.ServerAddrs = rpc_addrs
 | 
						cc.ServerAddrs = rpc_addrs
 | 
				
			||||||
	cc.PeerAddrs = peer_addrs
 | 
						cc.PeerAddrs = peer_addrs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	logger = &AppLogger{id: "client", out: os.Stderr, mask: log_mask}
 | 
						if log_file == "" {
 | 
				
			||||||
 | 
							logger = NewAppLogger("server", os.Stderr, log_mask)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							logger, err = NewAppLoggerToFile("server", log_file, log_mask)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("failed to initialize logger - %s", err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	c = hodu.NewClient(
 | 
						c = hodu.NewClient(
 | 
				
			||||||
		context.Background(),
 | 
							context.Background(),
 | 
				
			||||||
		logger,
 | 
							logger,
 | 
				
			||||||
@ -273,6 +315,7 @@ func client_main(ctl_addrs []string, rpc_addrs []string, peer_addrs []string, cf
 | 
				
			|||||||
	c.StartCtlService() // control channel
 | 
						c.StartCtlService() // control channel
 | 
				
			||||||
	c.StartExtService(&signal_handler{svc:c}, nil) // signal handler task
 | 
						c.StartExtService(&signal_handler{svc:c}, nil) // signal handler task
 | 
				
			||||||
	c.WaitForTermination()
 | 
						c.WaitForTermination()
 | 
				
			||||||
 | 
						logger.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								hodu.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								hodu.go
									
									
									
									
									
								
							@ -34,6 +34,7 @@ type Service interface {
 | 
				
			|||||||
	RunTask(wg *sync.WaitGroup) // blocking. run the actual task loop. it must call wg.Done() upon exit from itself.
 | 
						RunTask(wg *sync.WaitGroup) // blocking. run the actual task loop. it must call wg.Done() upon exit from itself.
 | 
				
			||||||
	StartService(data interface{}) // non-blocking. spin up a service. it may be invokded multiple times for multiple instances
 | 
						StartService(data interface{}) // non-blocking. spin up a service. it may be invokded multiple times for multiple instances
 | 
				
			||||||
	StopServices() // non-blocking. send stop request to all services spun up
 | 
						StopServices() // non-blocking. send stop request to all services spun up
 | 
				
			||||||
 | 
						FixServices() // do some fixup as needed
 | 
				
			||||||
	WaitForTermination() // blocking. must wait until all services are stopped
 | 
						WaitForTermination() // blocking. must wait until all services are stopped
 | 
				
			||||||
	WriteLog(id string, level LogLevel, fmtstr string, args ...interface{})
 | 
						WriteLog(id string, level LogLevel, fmtstr string, args ...interface{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user