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  }