github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/witch/logger.go (about) 1 package witch 2 3 import ( 4 "fmt" 5 "github.com/v2pro/plz/countlog" 6 "net/http" 7 "os" 8 "sync/atomic" 9 "time" 10 "github.com/json-iterator/go" 11 ) 12 13 var theEventQueue = newEventQueue() 14 15 type eventQueue struct { 16 msgChan chan []byte 17 droppedEventsCount uint64 18 } 19 20 func newEventQueue() *eventQueue { 21 return &eventQueue{ 22 msgChan: make(chan []byte, 10240), 23 } 24 } 25 26 func (q *eventQueue) Write(buf []byte) (int, error) { 27 select { 28 case q.msgChan <- buf: 29 default: 30 dropped := atomic.AddUint64(&q.droppedEventsCount, 1) 31 if dropped%10000 == 1 { 32 os.Stderr.Write([]byte(fmt.Sprintf( 33 "witch event queue overflow, dropped %v events since start\n", dropped))) 34 os.Stderr.Sync() 35 } 36 } 37 return len(buf), nil 38 } 39 40 func (q *eventQueue) consume() [][]byte { 41 events := make([][]byte, 0, 4) 42 timer := time.NewTimer(10 * time.Second) 43 select { 44 case event := <-theEventQueue.msgChan: 45 events = append(events, event) 46 case <-timer.C: 47 // timeout 48 } 49 time.Sleep(time.Millisecond * 10) 50 for { 51 select { 52 case event := <-theEventQueue.msgChan: 53 events = append(events, event) 54 if len(events) > 1000 { 55 return events 56 } 57 default: 58 return events 59 } 60 } 61 } 62 63 func moreEvents(respWriter http.ResponseWriter, req *http.Request) { 64 setCurrentGoRoutineIsKoala() 65 defer func() { 66 recovered := recover() 67 countlog.LogPanic(recovered) 68 }() 69 respWriter.Header().Add("Access-Control-Allow-Origin", "*") 70 respWriter.Write([]byte("[")) 71 stream := jsoniter.ConfigDefault.BorrowStream(respWriter) 72 defer jsoniter.ConfigDefault.ReturnStream(stream) 73 events := theEventQueue.consume() 74 stream.WriteArrayStart() 75 for i, event := range events { 76 if i != 0 { 77 stream.WriteMore() 78 } 79 stream.Write(event) 80 } 81 stream.WriteArrayEnd() 82 stream.Flush() 83 }