github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/util/log.go (about)

     1  package util
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"github.com/sirupsen/logrus"
     7  	"io"
     8  	"math"
     9  	"os/exec"
    10  	"runtime"
    11  	"strings"
    12  )
    13  
    14  type AddTraceHook struct {
    15  	Full bool
    16  }
    17  
    18  func (h *AddTraceHook) Levels() []logrus.Level {
    19  	return logrus.AllLevels
    20  }
    21  
    22  func (h *AddTraceHook) Fire(entry *logrus.Entry) error {
    23  	entry.Message = h.addTrace(entry.Message)
    24  	return nil
    25  }
    26  
    27  func (h *AddTraceHook) addTrace(message string) string {
    28  	skip := 2
    29  	ok := true
    30  	var stackTrace []string
    31  	for {
    32  		var pc uintptr
    33  		var fn string
    34  		var line int
    35  		pc, fn, line, ok = runtime.Caller(skip)
    36  		if !ok {
    37  			break
    38  		}
    39  		skip++
    40  
    41  		fnName := runtime.FuncForPC(pc).Name()
    42  		if strings.Contains(fnName, "logrus.") {
    43  			continue
    44  		}
    45  		fnNameComponents := strings.Split(fnName, "/")
    46  		truncatedFnName := fnNameComponents[len(fnNameComponents)-1]
    47  
    48  		pathComponents := strings.Split(fn, "/")
    49  		var truncatedPath string
    50  		if len(pathComponents) > 3 {
    51  			truncatedPath = strings.Join(pathComponents[len(pathComponents)-2:], "/")
    52  		} else {
    53  			truncatedPath = strings.Join(pathComponents, "/")
    54  		}
    55  		stackTrace = append(stackTrace, fmt.Sprintf("%s[%s:%d]", truncatedFnName, truncatedPath, line))
    56  		if !h.Full {
    57  			break
    58  		}
    59  	}
    60  
    61  	maxLen := int(math.Max(float64(len(stackTrace)-2), 1))
    62  	for i := 0; i < maxLen/2; i++ {
    63  		tmp := stackTrace[i]
    64  		stackTrace[i] = stackTrace[maxLen-i-1]
    65  		stackTrace[maxLen-i-1] = tmp
    66  	}
    67  	file := strings.Join(stackTrace[:maxLen], "\n")
    68  	message = file + "\n" + message
    69  	return message
    70  }
    71  
    72  func LogCommand(cmd *exec.Cmd, asDebug bool) {
    73  	logrus.WithField("command", cmd.Args).Debugf("running command")
    74  	stdout, err := cmd.StdoutPipe()
    75  	if err != nil {
    76  		return
    77  	}
    78  	stderr, err := cmd.StderrPipe()
    79  	if err != nil {
    80  		return
    81  	}
    82  	go func() {
    83  		in := bufio.NewScanner(stdout)
    84  		for in.Scan() {
    85  			if asDebug {
    86  				logrus.Debugf(in.Text())
    87  			} else {
    88  				logrus.Infof(in.Text())
    89  			}
    90  		}
    91  	}()
    92  	go func() {
    93  		in := bufio.NewScanner(stderr)
    94  		for in.Scan() {
    95  			logrus.Debugf(in.Text())
    96  		}
    97  	}()
    98  }
    99  
   100  type TeeHook struct {
   101  	W io.Writer
   102  }
   103  
   104  func (h *TeeHook) Levels() []logrus.Level {
   105  	return logrus.AllLevels
   106  }
   107  
   108  func (h *TeeHook) Fire(entry *logrus.Entry) error {
   109  	logger := logrus.New()
   110  	logger.Out = h.W
   111  	switch entry.Level {
   112  	case logrus.PanicLevel:
   113  		logger.WithFields(entry.Data).Panic(entry.Message)
   114  		break
   115  	case logrus.FatalLevel:
   116  		logger.WithFields(entry.Data).Fatal(entry.Message)
   117  		break
   118  	case logrus.ErrorLevel:
   119  		logger.WithFields(entry.Data).Error(entry.Message)
   120  		break
   121  	case logrus.WarnLevel:
   122  		logger.WithFields(entry.Data).Warnf(entry.Message)
   123  		break
   124  	case logrus.InfoLevel:
   125  		logger.WithFields(entry.Data).Info(entry.Message)
   126  		break
   127  	case logrus.DebugLevel:
   128  		logger.WithFields(entry.Data).Info(entry.Message)
   129  		break
   130  	}
   131  	return nil
   132  }