github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/log/conn.go (about) 1 // Copyright 2023 The GitBundle Inc. All rights reserved. 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file. 5 6 // Copyright 2014 The Gogs Authors. All rights reserved. 7 8 package log 9 10 import ( 11 "fmt" 12 "io" 13 "net" 14 15 "github.com/gitbundle/modules/json" 16 ) 17 18 type connWriter struct { 19 innerWriter io.WriteCloser 20 ReconnectOnMsg bool `json:"reconnectOnMsg"` 21 Reconnect bool `json:"reconnect"` 22 Net string `json:"net"` 23 Addr string `json:"addr"` 24 } 25 26 // Close the inner writer 27 func (i *connWriter) Close() error { 28 if i.innerWriter != nil { 29 return i.innerWriter.Close() 30 } 31 return nil 32 } 33 34 // Write the data to the connection 35 func (i *connWriter) Write(p []byte) (int, error) { 36 if i.neededConnectOnMsg() { 37 if err := i.connect(); err != nil { 38 return 0, err 39 } 40 } 41 42 if i.ReconnectOnMsg { 43 defer i.innerWriter.Close() 44 } 45 46 return i.innerWriter.Write(p) 47 } 48 49 func (i *connWriter) neededConnectOnMsg() bool { 50 if i.Reconnect { 51 i.Reconnect = false 52 return true 53 } 54 55 if i.innerWriter == nil { 56 return true 57 } 58 59 return i.ReconnectOnMsg 60 } 61 62 func (i *connWriter) connect() error { 63 if i.innerWriter != nil { 64 i.innerWriter.Close() 65 i.innerWriter = nil 66 } 67 68 conn, err := net.Dial(i.Net, i.Addr) 69 if err != nil { 70 return err 71 } 72 73 if tcpConn, ok := conn.(*net.TCPConn); ok { 74 err = tcpConn.SetKeepAlive(true) 75 if err != nil { 76 return err 77 } 78 } 79 80 i.innerWriter = conn 81 return nil 82 } 83 84 func (i *connWriter) releaseReopen() error { 85 if i.innerWriter != nil { 86 return i.connect() 87 } 88 return nil 89 } 90 91 // ConnLogger implements LoggerProvider. 92 // it writes messages in keep-live tcp connection. 93 type ConnLogger struct { 94 WriterLogger 95 ReconnectOnMsg bool `json:"reconnectOnMsg"` 96 Reconnect bool `json:"reconnect"` 97 Net string `json:"net"` 98 Addr string `json:"addr"` 99 } 100 101 // NewConn creates new ConnLogger returning as LoggerProvider. 102 func NewConn() LoggerProvider { 103 conn := new(ConnLogger) 104 conn.Level = TRACE 105 return conn 106 } 107 108 // Init inits connection writer with json config. 109 // json config only need key "level". 110 func (log *ConnLogger) Init(jsonconfig string) error { 111 err := json.Unmarshal([]byte(jsonconfig), log) 112 if err != nil { 113 return fmt.Errorf("Unable to parse JSON: %v", err) 114 } 115 log.NewWriterLogger(&connWriter{ 116 ReconnectOnMsg: log.ReconnectOnMsg, 117 Reconnect: log.Reconnect, 118 Net: log.Net, 119 Addr: log.Addr, 120 }, log.Level) 121 return nil 122 } 123 124 // Content returns the content accumulated in the content provider 125 func (log *ConnLogger) Content() (string, error) { 126 return "", fmt.Errorf("not supported") 127 } 128 129 // Flush does nothing for this implementation 130 func (log *ConnLogger) Flush() { 131 } 132 133 // GetName returns the default name for this implementation 134 func (log *ConnLogger) GetName() string { 135 return "conn" 136 } 137 138 // ReleaseReopen causes the ConnLogger to reconnect to the server 139 func (log *ConnLogger) ReleaseReopen() error { 140 return log.out.(*connWriter).releaseReopen() 141 } 142 143 func init() { 144 Register("conn", NewConn) 145 }