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