github.com/apex/up@v1.7.1/internal/logs/writer/writer.go (about)

     1  // Package writer provides an io.Writer for capturing
     2  // process output as logs, so that stdout may become
     3  // INFO, and stderr ERROR.
     4  package writer
     5  
     6  import (
     7  	"bufio"
     8  	"bytes"
     9  	"encoding/json"
    10  
    11  	"github.com/apex/log"
    12  	"github.com/apex/up/internal/util"
    13  )
    14  
    15  // Writer struct.
    16  type Writer struct {
    17  	log   log.Interface
    18  	level log.Level
    19  }
    20  
    21  // New writer with the given log level.
    22  func New(l log.Level, ctx log.Interface) *Writer {
    23  	return &Writer{
    24  		log:   ctx,
    25  		level: l,
    26  	}
    27  }
    28  
    29  // Write implementation.
    30  func (w *Writer) Write(b []byte) (int, error) {
    31  	s := bufio.NewScanner(bytes.NewReader(b))
    32  
    33  	for s.Scan() {
    34  		if err := w.write(s.Text()); err != nil {
    35  			return 0, err
    36  		}
    37  	}
    38  
    39  	if err := s.Err(); err != nil {
    40  		return 0, err
    41  	}
    42  
    43  	return len(b), nil
    44  }
    45  
    46  // write the line.
    47  func (w *Writer) write(s string) error {
    48  	if util.IsJSONLog(s) {
    49  		return w.writeJSON(s)
    50  	}
    51  
    52  	return w.writeText(s)
    53  }
    54  
    55  // writeJSON writes a json log, interpreting it as a log.Entry.
    56  func (w *Writer) writeJSON(s string) error {
    57  	// TODO: make this less ugly in apex/log,
    58  	// you should be able to write an arbitrary Entry.
    59  	var e log.Entry
    60  
    61  	if err := json.Unmarshal([]byte(s), &e); err != nil {
    62  		return w.writeText(s)
    63  	}
    64  
    65  	switch e.Level {
    66  	case log.DebugLevel:
    67  		w.log.WithFields(e.Fields).Debug(e.Message)
    68  	case log.InfoLevel:
    69  		w.log.WithFields(e.Fields).Info(e.Message)
    70  	case log.WarnLevel:
    71  		w.log.WithFields(e.Fields).Warn(e.Message)
    72  	case log.ErrorLevel:
    73  		w.log.WithFields(e.Fields).Error(e.Message)
    74  	case log.FatalLevel:
    75  		// TODO: FATAL without exit...
    76  		w.log.WithFields(e.Fields).Error(e.Message)
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  // writeText writes plain text.
    83  func (w *Writer) writeText(s string) error {
    84  	switch w.level {
    85  	case log.InfoLevel:
    86  		w.log.Info(s)
    87  	case log.ErrorLevel:
    88  		w.log.Error(s)
    89  	}
    90  	return nil
    91  }