logger.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright 2017 Unknwon
  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 clog
  15. import "fmt"
  16. // Logger is an interface for a logger adapter with specific mode and level.
  17. type Logger interface {
  18. // Level returns minimum level of given logger.
  19. Level() LEVEL
  20. // Init accepts a config struct specific for given logger and performs any necessary initialization.
  21. Init(interface{}) error
  22. // ExchangeChans accepts error channel, and returns message receive channel.
  23. ExchangeChans(chan<- error) chan *Message
  24. // Start starts message processing.
  25. Start()
  26. // Destroy releases all resources.
  27. Destroy()
  28. }
  29. // Adapter contains common fields for any logger adapter. This struct should be used as embedded struct.
  30. type Adapter struct {
  31. level LEVEL
  32. msgChan chan *Message
  33. quitChan chan struct{}
  34. errorChan chan<- error
  35. }
  36. type Factory func() Logger
  37. // factories keeps factory function of registered loggers.
  38. var factories = map[MODE]Factory{}
  39. func Register(mode MODE, f Factory) {
  40. if f == nil {
  41. panic("clog: register function is nil")
  42. }
  43. if factories[mode] != nil {
  44. panic("clog: register duplicated mode '" + mode + "'")
  45. }
  46. factories[mode] = f
  47. }
  48. type receiver struct {
  49. Logger
  50. mode MODE
  51. msgChan chan *Message
  52. }
  53. var (
  54. // receivers is a list of loggers with their message channel for broadcasting.
  55. receivers []*receiver
  56. errorChan = make(chan error, 5)
  57. quitChan = make(chan struct{})
  58. )
  59. func init() {
  60. // Start background error handling goroutine.
  61. go func() {
  62. for {
  63. select {
  64. case err := <-errorChan:
  65. fmt.Printf("clog: unable to write message: %v\n", err)
  66. case <-quitChan:
  67. return
  68. }
  69. }
  70. }()
  71. }
  72. // New initializes and appends a new logger to the receiver list.
  73. // Calling this function multiple times will overwrite previous logger with same mode.
  74. func New(mode MODE, cfg interface{}) error {
  75. factory, ok := factories[mode]
  76. if !ok {
  77. return fmt.Errorf("unknown mode '%s'", mode)
  78. }
  79. logger := factory()
  80. if err := logger.Init(cfg); err != nil {
  81. return err
  82. }
  83. msgChan := logger.ExchangeChans(errorChan)
  84. // Check and replace previous logger.
  85. hasFound := false
  86. for i := range receivers {
  87. if receivers[i].mode == mode {
  88. hasFound = true
  89. // Release previous logger.
  90. receivers[i].Destroy()
  91. // Update info to new one.
  92. receivers[i].Logger = logger
  93. receivers[i].msgChan = msgChan
  94. break
  95. }
  96. }
  97. if !hasFound {
  98. receivers = append(receivers, &receiver{
  99. Logger: logger,
  100. mode: mode,
  101. msgChan: msgChan,
  102. })
  103. }
  104. go logger.Start()
  105. return nil
  106. }
  107. // Delete removes logger from the receiver list.
  108. func Delete(mode MODE) {
  109. foundIdx := -1
  110. for i := range receivers {
  111. if receivers[i].mode == mode {
  112. foundIdx = i
  113. receivers[i].Destroy()
  114. }
  115. }
  116. if foundIdx >= 0 {
  117. newList := make([]*receiver, len(receivers)-1)
  118. copy(newList, receivers[:foundIdx])
  119. copy(newList[foundIdx:], receivers[foundIdx+1:])
  120. receivers = newList
  121. }
  122. }