github.com/cmalfait/terraform@v0.11.12-beta1/helper/logging/logging.go (about) 1 package logging 2 3 import ( 4 "io" 5 "io/ioutil" 6 "log" 7 "os" 8 "strings" 9 "syscall" 10 11 "github.com/hashicorp/logutils" 12 ) 13 14 // These are the environmental variables that determine if we log, and if 15 // we log whether or not the log should go to a file. 16 const ( 17 EnvLog = "TF_LOG" // Set to True 18 EnvLogFile = "TF_LOG_PATH" // Set to a file 19 ) 20 21 var ValidLevels = []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERROR"} 22 23 // LogOutput determines where we should send logs (if anywhere) and the log level. 24 func LogOutput() (logOutput io.Writer, err error) { 25 logOutput = ioutil.Discard 26 27 logLevel := LogLevel() 28 if logLevel == "" { 29 return 30 } 31 32 logOutput = os.Stderr 33 if logPath := os.Getenv(EnvLogFile); logPath != "" { 34 var err error 35 logOutput, err = os.OpenFile(logPath, syscall.O_CREAT|syscall.O_RDWR|syscall.O_APPEND, 0666) 36 if err != nil { 37 return nil, err 38 } 39 } 40 41 // This was the default since the beginning 42 logOutput = &logutils.LevelFilter{ 43 Levels: ValidLevels, 44 MinLevel: logutils.LogLevel(logLevel), 45 Writer: logOutput, 46 } 47 48 return 49 } 50 51 // SetOutput checks for a log destination with LogOutput, and calls 52 // log.SetOutput with the result. If LogOutput returns nil, SetOutput uses 53 // ioutil.Discard. Any error from LogOutout is fatal. 54 func SetOutput() { 55 out, err := LogOutput() 56 if err != nil { 57 log.Fatal(err) 58 } 59 60 if out == nil { 61 out = ioutil.Discard 62 } 63 64 log.SetOutput(out) 65 } 66 67 // LogLevel returns the current log level string based the environment vars 68 func LogLevel() string { 69 envLevel := os.Getenv(EnvLog) 70 if envLevel == "" { 71 return "" 72 } 73 74 logLevel := "TRACE" 75 if isValidLogLevel(envLevel) { 76 // allow following for better ux: info, Info or INFO 77 logLevel = strings.ToUpper(envLevel) 78 } else { 79 log.Printf("[WARN] Invalid log level: %q. Defaulting to level: TRACE. Valid levels are: %+v", 80 envLevel, ValidLevels) 81 } 82 83 return logLevel 84 } 85 86 // IsDebugOrHigher returns whether or not the current log level is debug or trace 87 func IsDebugOrHigher() bool { 88 level := string(LogLevel()) 89 return level == "DEBUG" || level == "TRACE" 90 } 91 92 func isValidLogLevel(level string) bool { 93 for _, l := range ValidLevels { 94 if strings.ToUpper(level) == string(l) { 95 return true 96 } 97 } 98 99 return false 100 }