You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

118 lines
2.8 KiB

  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. )
  20. // NewLoggingConn returns a logging wrapper around a connection.
  21. func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn {
  22. if prefix != "" {
  23. prefix = prefix + "."
  24. }
  25. return &loggingConn{conn, logger, prefix}
  26. }
  27. type loggingConn struct {
  28. Conn
  29. logger *log.Logger
  30. prefix string
  31. }
  32. func (c *loggingConn) Close() error {
  33. err := c.Conn.Close()
  34. var buf bytes.Buffer
  35. fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err)
  36. c.logger.Output(2, buf.String())
  37. return err
  38. }
  39. func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) {
  40. const chop = 32
  41. switch v := v.(type) {
  42. case []byte:
  43. if len(v) > chop {
  44. fmt.Fprintf(buf, "%q...", v[:chop])
  45. } else {
  46. fmt.Fprintf(buf, "%q", v)
  47. }
  48. case string:
  49. if len(v) > chop {
  50. fmt.Fprintf(buf, "%q...", v[:chop])
  51. } else {
  52. fmt.Fprintf(buf, "%q", v)
  53. }
  54. case []interface{}:
  55. if len(v) == 0 {
  56. buf.WriteString("[]")
  57. } else {
  58. sep := "["
  59. fin := "]"
  60. if len(v) > chop {
  61. v = v[:chop]
  62. fin = "...]"
  63. }
  64. for _, vv := range v {
  65. buf.WriteString(sep)
  66. c.printValue(buf, vv)
  67. sep = ", "
  68. }
  69. buf.WriteString(fin)
  70. }
  71. default:
  72. fmt.Fprint(buf, v)
  73. }
  74. }
  75. func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) {
  76. var buf bytes.Buffer
  77. fmt.Fprintf(&buf, "%s%s(", c.prefix, method)
  78. if method != "Receive" {
  79. buf.WriteString(commandName)
  80. for _, arg := range args {
  81. buf.WriteString(", ")
  82. c.printValue(&buf, arg)
  83. }
  84. }
  85. buf.WriteString(") -> (")
  86. if method != "Send" {
  87. c.printValue(&buf, reply)
  88. buf.WriteString(", ")
  89. }
  90. fmt.Fprintf(&buf, "%v)", err)
  91. c.logger.Output(3, buf.String())
  92. }
  93. func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) {
  94. reply, err := c.Conn.Do(commandName, args...)
  95. c.print("Do", commandName, args, reply, err)
  96. return reply, err
  97. }
  98. func (c *loggingConn) Send(commandName string, args ...interface{}) error {
  99. err := c.Conn.Send(commandName, args...)
  100. c.print("Send", commandName, args, nil, err)
  101. return err
  102. }
  103. func (c *loggingConn) Receive() (interface{}, error) {
  104. reply, err := c.Conn.Receive()
  105. c.print("Receive", "", nil, reply, err)
  106. return reply, err
  107. }