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  }