1package agent 2 3import ( 4 "log" 5 6 "github.com/hashicorp/logutils" 7) 8 9// logStream is used to stream logs to a client over IPC 10type logStream struct { 11 client streamClient 12 filter *logutils.LevelFilter 13 logCh chan string 14 logger *log.Logger 15 seq uint64 16} 17 18func newLogStream(client streamClient, filter *logutils.LevelFilter, 19 seq uint64, logger *log.Logger) *logStream { 20 ls := &logStream{ 21 client: client, 22 filter: filter, 23 logCh: make(chan string, 512), 24 logger: logger, 25 seq: seq, 26 } 27 go ls.stream() 28 return ls 29} 30 31func (ls *logStream) HandleLog(l string) { 32 // Check the log level 33 if !ls.filter.Check([]byte(l)) { 34 return 35 } 36 37 // Do a non-blocking send 38 select { 39 case ls.logCh <- l: 40 default: 41 // We can't log syncronously, since we are already being invoked 42 // from the logWriter, and a log will need to invoke Write() which 43 // already holds the lock. We must therefor do the log async, so 44 // as to not deadlock 45 go ls.logger.Printf("[WARN] agent.ipc: Dropping logs to %v", ls.client) 46 } 47} 48 49func (ls *logStream) Stop() { 50 close(ls.logCh) 51} 52 53func (ls *logStream) stream() { 54 header := responseHeader{Seq: ls.seq, Error: ""} 55 rec := logRecord{Log: ""} 56 57 for line := range ls.logCh { 58 rec.Log = line 59 if err := ls.client.Send(&header, &rec); err != nil { 60 ls.logger.Printf("[ERR] agent.ipc: Failed to stream log to %v: %v", 61 ls.client, err) 62 return 63 } 64 } 65} 66