debug_on.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // +build debug OR debug0
  2. package pdebug
  3. import (
  4. "bytes"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "github.com/davecgh/go-spew/spew"
  9. )
  10. const Enabled = true
  11. type Guard interface {
  12. End()
  13. }
  14. var emptyGuard = &guard{}
  15. func (ctx *pdctx) Unindent() {
  16. ctx.mutex.Lock()
  17. defer ctx.mutex.Unlock()
  18. ctx.indentL--
  19. }
  20. func (ctx *pdctx) Indent() guard {
  21. ctx.mutex.Lock()
  22. ctx.indentL++
  23. ctx.mutex.Unlock()
  24. return guard{cb: ctx.Unindent}
  25. }
  26. func (ctx *pdctx) preamble(buf *bytes.Buffer) {
  27. if p := ctx.Prefix; len(p) > 0 {
  28. buf.WriteString(p)
  29. }
  30. if ctx.LogTime {
  31. fmt.Fprintf(buf, "%0.5f ", float64(time.Now().UnixNano()) / 1000000.0)
  32. }
  33. for i := 0; i < ctx.indentL; i++ {
  34. buf.WriteString(" ")
  35. }
  36. }
  37. func (ctx *pdctx) Printf(f string, args ...interface{}) {
  38. if !strings.HasSuffix(f, "\n") {
  39. f = f + "\n"
  40. }
  41. buf := bytes.Buffer{}
  42. ctx.preamble(&buf)
  43. fmt.Fprintf(&buf, f, args...)
  44. buf.WriteTo(ctx.Writer)
  45. }
  46. func Marker(f string, args ...interface{}) *markerg {
  47. return DefaultCtx.Marker(f, args...)
  48. }
  49. func (ctx *pdctx) Marker(f string, args ...interface{}) *markerg {
  50. if !Trace {
  51. return emptyMarkerGuard
  52. }
  53. buf := &bytes.Buffer{}
  54. ctx.preamble(buf)
  55. buf.WriteString("START ")
  56. fmt.Fprintf(buf, f, args...)
  57. if buf.Len() > 0 {
  58. if b := buf.Bytes(); b[buf.Len()-1] != '\n' {
  59. buf.WriteRune('\n')
  60. }
  61. }
  62. buf.WriteTo(ctx.Writer)
  63. g := ctx.Indent()
  64. return &markerg{
  65. indentg: g,
  66. ctx: ctx,
  67. f: f,
  68. args: args,
  69. start: time.Now(),
  70. errptr: nil,
  71. }
  72. }
  73. func (g *markerg) BindError(errptr *error) *markerg {
  74. if g.ctx == nil {
  75. return g
  76. }
  77. g.ctx.mutex.Lock()
  78. defer g.ctx.mutex.Unlock()
  79. g.errptr = errptr
  80. return g
  81. }
  82. func (g *markerg) End() {
  83. if g.ctx == nil {
  84. return
  85. }
  86. g.indentg.End() // unindent
  87. buf := &bytes.Buffer{}
  88. g.ctx.preamble(buf)
  89. fmt.Fprint(buf, "END ")
  90. fmt.Fprintf(buf, g.f, g.args...)
  91. fmt.Fprintf(buf, " (%s)", time.Since(g.start))
  92. if errptr := g.errptr; errptr != nil && *errptr != nil {
  93. fmt.Fprintf(buf, ": ERROR: %s", *errptr)
  94. }
  95. if buf.Len() > 0 {
  96. if b := buf.Bytes(); b[buf.Len()-1] != '\n' {
  97. buf.WriteRune('\n')
  98. }
  99. }
  100. buf.WriteTo(g.ctx.Writer)
  101. }
  102. type legacyg struct {
  103. guard
  104. start time.Time
  105. }
  106. var emptylegacyg = legacyg{}
  107. func (g legacyg) IRelease(f string, args ...interface{}) {
  108. if !Trace {
  109. return
  110. }
  111. g.End()
  112. dur := time.Since(g.start)
  113. Printf("%s (%s)", fmt.Sprintf(f, args...), dur)
  114. }
  115. // IPrintf indents and then prints debug messages. Execute the callback
  116. // to undo the indent
  117. func IPrintf(f string, args ...interface{}) legacyg {
  118. if !Trace {
  119. return emptylegacyg
  120. }
  121. DefaultCtx.Printf(f, args...)
  122. g := legacyg{
  123. guard: DefaultCtx.Indent(),
  124. start: time.Now(),
  125. }
  126. return g
  127. }
  128. // Printf prints debug messages. Only available if compiled with "debug" tag
  129. func Printf(f string, args ...interface{}) {
  130. if !Trace {
  131. return
  132. }
  133. DefaultCtx.Printf(f, args...)
  134. }
  135. func Dump(v ...interface{}) {
  136. if !Trace {
  137. return
  138. }
  139. spew.Dump(v...)
  140. }