log.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright 2012 Gary Burd
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. // License for the specific language governing permissions and limitations
  13. // under the License.
  14. package redis
  15. import (
  16. "bytes"
  17. "fmt"
  18. "log"
  19. "time"
  20. )
  21. var (
  22. _ ConnWithTimeout = (*loggingConn)(nil)
  23. )
  24. // NewLoggingConn returns a logging wrapper around a connection.
  25. func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn {
  26. if prefix != "" {
  27. prefix = prefix + "."
  28. }
  29. return &loggingConn{conn, logger, prefix, nil}
  30. }
  31. //NewLoggingConnFilter returns a logging wrapper around a connection and a filter function.
  32. func NewLoggingConnFilter(conn Conn, logger *log.Logger, prefix string, skip func(cmdName string) bool) Conn {
  33. if prefix != "" {
  34. prefix = prefix + "."
  35. }
  36. return &loggingConn{conn, logger, prefix, skip}
  37. }
  38. type loggingConn struct {
  39. Conn
  40. logger *log.Logger
  41. prefix string
  42. skip func(cmdName string) bool
  43. }
  44. func (c *loggingConn) Close() error {
  45. err := c.Conn.Close()
  46. var buf bytes.Buffer
  47. fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err)
  48. c.logger.Output(2, buf.String()) // nolint: errcheck
  49. return err
  50. }
  51. func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) {
  52. const chop = 32
  53. switch v := v.(type) {
  54. case []byte:
  55. if len(v) > chop {
  56. fmt.Fprintf(buf, "%q...", v[:chop])
  57. } else {
  58. fmt.Fprintf(buf, "%q", v)
  59. }
  60. case string:
  61. if len(v) > chop {
  62. fmt.Fprintf(buf, "%q...", v[:chop])
  63. } else {
  64. fmt.Fprintf(buf, "%q", v)
  65. }
  66. case []interface{}:
  67. if len(v) == 0 {
  68. buf.WriteString("[]")
  69. } else {
  70. sep := "["
  71. fin := "]"
  72. if len(v) > chop {
  73. v = v[:chop]
  74. fin = "...]"
  75. }
  76. for _, vv := range v {
  77. buf.WriteString(sep)
  78. c.printValue(buf, vv)
  79. sep = ", "
  80. }
  81. buf.WriteString(fin)
  82. }
  83. default:
  84. fmt.Fprint(buf, v)
  85. }
  86. }
  87. func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) {
  88. if c.skip != nil && c.skip(commandName) {
  89. return
  90. }
  91. var buf bytes.Buffer
  92. fmt.Fprintf(&buf, "%s%s(", c.prefix, method)
  93. if method != "Receive" {
  94. buf.WriteString(commandName)
  95. for _, arg := range args {
  96. buf.WriteString(", ")
  97. c.printValue(&buf, arg)
  98. }
  99. }
  100. buf.WriteString(") -> (")
  101. if method != "Send" {
  102. c.printValue(&buf, reply)
  103. buf.WriteString(", ")
  104. }
  105. fmt.Fprintf(&buf, "%v)", err)
  106. c.logger.Output(3, buf.String()) // nolint: errcheck
  107. }
  108. func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) {
  109. reply, err := c.Conn.Do(commandName, args...)
  110. c.print("Do", commandName, args, reply, err)
  111. return reply, err
  112. }
  113. func (c *loggingConn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (interface{}, error) {
  114. reply, err := DoWithTimeout(c.Conn, timeout, commandName, args...)
  115. c.print("DoWithTimeout", commandName, args, reply, err)
  116. return reply, err
  117. }
  118. func (c *loggingConn) Send(commandName string, args ...interface{}) error {
  119. err := c.Conn.Send(commandName, args...)
  120. c.print("Send", commandName, args, nil, err)
  121. return err
  122. }
  123. func (c *loggingConn) Receive() (interface{}, error) {
  124. reply, err := c.Conn.Receive()
  125. c.print("Receive", "", nil, reply, err)
  126. return reply, err
  127. }
  128. func (c *loggingConn) ReceiveWithTimeout(timeout time.Duration) (interface{}, error) {
  129. reply, err := ReceiveWithTimeout(c.Conn, timeout)
  130. c.print("ReceiveWithTimeout", "", nil, reply, err)
  131. return reply, err
  132. }