writer.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package srslog
  2. import (
  3. "crypto/tls"
  4. "strings"
  5. "sync"
  6. )
  7. // A Writer is a connection to a syslog server.
  8. type Writer struct {
  9. sync.Mutex // guards conn
  10. priority Priority
  11. tag string
  12. hostname string
  13. network string
  14. raddr string
  15. tlsConfig *tls.Config
  16. framer Framer
  17. formatter Formatter
  18. conn serverConn
  19. }
  20. // connect makes a connection to the syslog server.
  21. // It must be called with w.mu held.
  22. func (w *Writer) connect() (err error) {
  23. if w.conn != nil {
  24. // ignore err from close, it makes sense to continue anyway
  25. w.conn.close()
  26. w.conn = nil
  27. }
  28. var conn serverConn
  29. var hostname string
  30. dialer := w.getDialer()
  31. conn, hostname, err = dialer.Call()
  32. if err == nil {
  33. w.conn = conn
  34. w.hostname = hostname
  35. }
  36. return
  37. }
  38. // SetFormatter changes the formatter function for subsequent messages.
  39. func (w *Writer) SetFormatter(f Formatter) {
  40. w.formatter = f
  41. }
  42. // SetFramer changes the framer function for subsequent messages.
  43. func (w *Writer) SetFramer(f Framer) {
  44. w.framer = f
  45. }
  46. // Write sends a log message to the syslog daemon using the default priority
  47. // passed into `srslog.New` or the `srslog.Dial*` functions.
  48. func (w *Writer) Write(b []byte) (int, error) {
  49. return w.writeAndRetry(w.priority, string(b))
  50. }
  51. // Close closes a connection to the syslog daemon.
  52. func (w *Writer) Close() error {
  53. w.Lock()
  54. defer w.Unlock()
  55. if w.conn != nil {
  56. err := w.conn.close()
  57. w.conn = nil
  58. return err
  59. }
  60. return nil
  61. }
  62. // Emerg logs a message with severity LOG_EMERG; this overrides the default
  63. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  64. func (w *Writer) Emerg(m string) (err error) {
  65. _, err = w.writeAndRetry(LOG_EMERG, m)
  66. return err
  67. }
  68. // Alert logs a message with severity LOG_ALERT; this overrides the default
  69. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  70. func (w *Writer) Alert(m string) (err error) {
  71. _, err = w.writeAndRetry(LOG_ALERT, m)
  72. return err
  73. }
  74. // Crit logs a message with severity LOG_CRIT; this overrides the default
  75. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  76. func (w *Writer) Crit(m string) (err error) {
  77. _, err = w.writeAndRetry(LOG_CRIT, m)
  78. return err
  79. }
  80. // Err logs a message with severity LOG_ERR; this overrides the default
  81. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  82. func (w *Writer) Err(m string) (err error) {
  83. _, err = w.writeAndRetry(LOG_ERR, m)
  84. return err
  85. }
  86. // Warning logs a message with severity LOG_WARNING; this overrides the default
  87. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  88. func (w *Writer) Warning(m string) (err error) {
  89. _, err = w.writeAndRetry(LOG_WARNING, m)
  90. return err
  91. }
  92. // Notice logs a message with severity LOG_NOTICE; this overrides the default
  93. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  94. func (w *Writer) Notice(m string) (err error) {
  95. _, err = w.writeAndRetry(LOG_NOTICE, m)
  96. return err
  97. }
  98. // Info logs a message with severity LOG_INFO; this overrides the default
  99. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  100. func (w *Writer) Info(m string) (err error) {
  101. _, err = w.writeAndRetry(LOG_INFO, m)
  102. return err
  103. }
  104. // Debug logs a message with severity LOG_DEBUG; this overrides the default
  105. // priority passed to `srslog.New` and the `srslog.Dial*` functions.
  106. func (w *Writer) Debug(m string) (err error) {
  107. _, err = w.writeAndRetry(LOG_DEBUG, m)
  108. return err
  109. }
  110. func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
  111. pr := (w.priority & facilityMask) | (p & severityMask)
  112. w.Lock()
  113. defer w.Unlock()
  114. if w.conn != nil {
  115. if n, err := w.write(pr, s); err == nil {
  116. return n, err
  117. }
  118. }
  119. if err := w.connect(); err != nil {
  120. return 0, err
  121. }
  122. return w.write(pr, s)
  123. }
  124. // write generates and writes a syslog formatted string. It formats the
  125. // message based on the current Formatter and Framer.
  126. func (w *Writer) write(p Priority, msg string) (int, error) {
  127. // ensure it ends in a \n
  128. if !strings.HasSuffix(msg, "\n") {
  129. msg += "\n"
  130. }
  131. err := w.conn.writeString(w.framer, w.formatter, p, w.hostname, w.tag, msg)
  132. if err != nil {
  133. return 0, err
  134. }
  135. // Note: return the length of the input, not the number of
  136. // bytes printed by Fprintf, because this must behave like
  137. // an io.Writer.
  138. return len(msg), nil
  139. }