github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/service/log_queue.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package service
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  
    10  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    11  )
    12  
    13  type logQueue struct {
    14  	name     string
    15  	level    keybase1.LogLevel
    16  	ui       *LogUI
    17  	handleID int
    18  	buffer   chan *logEntry
    19  	drop     chan bool
    20  }
    21  
    22  func newLogQueue(name string, level keybase1.LogLevel, ui *LogUI) *logQueue {
    23  	q := &logQueue{
    24  		name:   name,
    25  		level:  level,
    26  		ui:     ui,
    27  		buffer: make(chan *logEntry, 10000),
    28  		drop:   make(chan bool, 1),
    29  	}
    30  
    31  	go q.processQueue()
    32  
    33  	return q
    34  }
    35  
    36  func (q *logQueue) String() string {
    37  	return fmt.Sprintf("%s: level %d, handle id %d", q.name, q.level, q.handleID)
    38  }
    39  
    40  func (q *logQueue) SetHandleID(id int) {
    41  	q.handleID = id
    42  }
    43  
    44  func (q *logQueue) HandleID() int {
    45  	return q.handleID
    46  }
    47  
    48  func (q *logQueue) Log(e *logEntry) {
    49  	if e.level < q.level {
    50  		return
    51  	}
    52  	select {
    53  	case q.buffer <- e:
    54  		q.checkDropFlag()
    55  	default:
    56  		q.setDropFlag()
    57  	}
    58  }
    59  
    60  func (q *logQueue) Shutdown() {
    61  	close(q.buffer)
    62  	q.buffer = nil
    63  }
    64  
    65  func (q *logQueue) processQueue() {
    66  	for e := range q.buffer {
    67  		if e.level < q.level {
    68  			continue
    69  		}
    70  		q.ui.Log(e.level, e.format, e.args)
    71  	}
    72  }
    73  
    74  // setDropFlag puts a flag into the drop channel if the channel is
    75  // empty.  This is to signal that external log messages have been
    76  // dropped.
    77  func (q *logQueue) setDropFlag() {
    78  	select {
    79  	case q.drop <- true:
    80  		// do this outside the logging mechanism to make sure it gets through
    81  		fmt.Fprintf(os.Stderr, "WARNING: dropping log messages destined for %q due to full log buffer\n", q.name)
    82  	default:
    83  	}
    84  }
    85  
    86  // checkDropFlag checks to see if anything is in the drop channel.
    87  // If there is a flag in there, it will warn client that log
    88  // messages were dropped.
    89  func (q *logQueue) checkDropFlag() {
    90  	select {
    91  	case <-q.drop:
    92  		q.buffer <- &logEntry{
    93  			level:  keybase1.LogLevel_WARN,
    94  			format: "Service log messages were dropped due to full buffer",
    95  		}
    96  	default:
    97  	}
    98  }