context.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package log
  2. import (
  3. "context"
  4. "github.com/sirupsen/logrus"
  5. "go.opencensus.io/trace"
  6. )
  7. type entryContextKeyType int
  8. const _entryContextKey entryContextKeyType = iota
  9. var (
  10. // L is the default, blank logging entry. WithField and co. all return a copy
  11. // of the original entry, so this will not leak fields between calls.
  12. //
  13. // Do NOT modify fields directly, as that will corrupt state for all users and
  14. // is not thread safe.
  15. // Instead, use `L.With*` or `L.Dup()`. Or `G(context.Background())`.
  16. L = logrus.NewEntry(logrus.StandardLogger())
  17. // G is an alias for GetEntry
  18. G = GetEntry
  19. // S is an alias for SetEntry
  20. S = SetEntry
  21. // U is an alias for UpdateContext
  22. U = UpdateContext
  23. )
  24. // GetEntry returns a `logrus.Entry` stored in the context, if one exists.
  25. // Otherwise, it returns a default entry that points to the current context.
  26. //
  27. // Note: if the a new entry is returned, it will reference the passed in context.
  28. // However, existing contexts may be stored in parent contexts and additionally reference
  29. // earlier contexts.
  30. // Use `UpdateContext` to update the entry and context.
  31. func GetEntry(ctx context.Context) *logrus.Entry {
  32. entry := fromContext(ctx)
  33. if entry == nil {
  34. entry = L.WithContext(ctx)
  35. }
  36. return entry
  37. }
  38. // SetEntry updates the log entry in the context with the provided fields, and
  39. // returns both. It is equivalent to:
  40. //
  41. // entry := GetEntry(ctx).WithFields(fields)
  42. // ctx = WithContext(ctx, entry)
  43. //
  44. // See WithContext for more information.
  45. func SetEntry(ctx context.Context, fields logrus.Fields) (context.Context, *logrus.Entry) {
  46. e := GetEntry(ctx)
  47. if len(fields) > 0 {
  48. e = e.WithFields(fields)
  49. }
  50. return WithContext(ctx, e)
  51. }
  52. // UpdateContext extracts the log entry from the context, and, if the entry's
  53. // context points to a parent's of the current context, ands the entry
  54. // to the most recent context. It is equivalent to:
  55. //
  56. // entry := GetEntry(ctx)
  57. // ctx = WithContext(ctx, entry)
  58. //
  59. // This allows the entry to reference the most recent context and any new
  60. // values (such as span contexts) added to it.
  61. //
  62. // See WithContext for more information.
  63. func UpdateContext(ctx context.Context) context.Context {
  64. // there is no way to check its ctx (and not one of its parents) that contains `e`
  65. // so, at a slight cost, force add `e` to the context
  66. ctx, _ = WithContext(ctx, GetEntry(ctx))
  67. return ctx
  68. }
  69. // WithContext returns a context that contains the provided log entry.
  70. // The entry can be extracted with `GetEntry` (`G`)
  71. //
  72. // The entry in the context is a copy of `entry` (generated by `entry.WithContext`)
  73. func WithContext(ctx context.Context, entry *logrus.Entry) (context.Context, *logrus.Entry) {
  74. // regardless of the order, entry.Context != GetEntry(ctx)
  75. // here, the returned entry will reference the supplied context
  76. entry = entry.WithContext(ctx)
  77. ctx = context.WithValue(ctx, _entryContextKey, entry)
  78. return ctx, entry
  79. }
  80. // Copy extracts the tracing Span and logging entry from the src Context, if they
  81. // exist, and adds them to the dst Context.
  82. //
  83. // This is useful to share tracing and logging between contexts, but not the
  84. // cancellation. For example, if the src Context has been cancelled but cleanup
  85. // operations triggered by the cancellation require a non-cancelled context to
  86. // execute.
  87. func Copy(dst context.Context, src context.Context) context.Context {
  88. if s := trace.FromContext(src); s != nil {
  89. dst = trace.NewContext(dst, s)
  90. }
  91. if e := fromContext(src); e != nil {
  92. dst, _ = WithContext(dst, e)
  93. }
  94. return dst
  95. }
  96. func fromContext(ctx context.Context) *logrus.Entry {
  97. e, _ := ctx.Value(_entryContextKey).(*logrus.Entry)
  98. return e
  99. }