2015-12-08 01:10:30 +01:00
package logging
2014-05-31 01:07:26 +02:00
import (
2020-10-17 15:38:18 +02:00
"fmt"
2014-05-31 01:07:26 +02:00
"io"
2015-12-08 01:10:30 +01:00
"io/ioutil"
2015-10-01 21:45:12 +02:00
"log"
2014-05-31 01:07:26 +02:00
"os"
2015-10-01 21:45:12 +02:00
"strings"
2016-10-18 22:08:23 +02:00
"syscall"
2020-10-17 15:38:18 +02:00
"github.com/hashicorp/go-hclog"
2014-05-31 01:07:26 +02:00
)
// These are the environmental variables that determine if we log, and if
// we log whether or not the log should go to a file.
2015-10-01 21:45:12 +02:00
const (
EnvLog = "TF_LOG" // Set to True
EnvLogFile = "TF_LOG_PATH" // Set to a file
)
2014-05-31 01:07:26 +02:00
2019-12-05 20:13:37 +01:00
// ValidLevels are the log level names that Terraform recognizes.
2020-10-18 17:25:44 +02:00
var ValidLevels = [ ] string { "TRACE" , "DEBUG" , "INFO" , "WARN" , "ERROR" }
2015-10-01 21:45:12 +02:00
2020-10-17 15:38:18 +02:00
// logger is the global hclog logger
var logger hclog . Logger
2016-03-14 17:17:05 +01:00
2020-10-18 16:01:48 +02:00
// logWriter is a global writer for logs, to be used with the std log package
var logWriter io . Writer
2020-10-17 15:38:18 +02:00
func init ( ) {
2020-10-17 15:57:03 +02:00
logger = NewHCLogger ( "" )
2020-10-18 16:01:48 +02:00
logWriter = logger . StandardWriter ( & hclog . StandardLoggerOptions { InferLevels : true } )
// setup the default std library logger to use our output
log . SetFlags ( 0 )
log . SetPrefix ( "" )
log . SetOutput ( logWriter )
2020-10-17 15:57:03 +02:00
}
2020-10-18 16:01:48 +02:00
// LogOutput return the default global log io.Writer
func LogOutput ( ) io . Writer {
return logWriter
2020-10-17 15:57:03 +02:00
}
2020-10-18 16:01:48 +02:00
// HCLogger returns the default global hclog logger
2020-10-17 15:57:03 +02:00
func HCLogger ( ) hclog . Logger {
return logger
}
// NewHCLogger returns a new hclog.Logger instance with the given name
func NewHCLogger ( name string ) hclog . Logger {
2020-10-17 15:38:18 +02:00
logOutput := io . Writer ( os . Stderr )
2019-12-05 20:13:37 +01:00
logLevel := CurrentLogLevel ( )
2016-03-14 17:17:05 +01:00
if logLevel == "" {
2020-10-17 15:38:18 +02:00
logOutput = ioutil . Discard
2015-10-01 21:45:12 +02:00
}
if logPath := os . Getenv ( EnvLogFile ) ; logPath != "" {
2020-10-17 15:38:18 +02:00
f , err := os . OpenFile ( logPath , syscall . O_CREAT | syscall . O_RDWR | syscall . O_APPEND , 0666 )
2015-10-01 21:45:12 +02:00
if err != nil {
2020-10-17 15:38:18 +02:00
fmt . Fprintf ( os . Stderr , "Error opening log file: %v\n" , err )
} else {
logOutput = f
2014-05-31 01:07:26 +02:00
}
}
2020-10-17 15:57:03 +02:00
return hclog . New ( & hclog . LoggerOptions {
Name : name ,
2020-10-17 15:38:18 +02:00
Level : hclog . LevelFromString ( logLevel ) ,
Output : logOutput ,
} )
}
2019-12-05 21:19:22 +01:00
2019-12-05 20:13:37 +01:00
// CurrentLogLevel returns the current log level string based the environment vars
func CurrentLogLevel ( ) string {
2020-10-17 15:38:18 +02:00
envLevel := strings . ToUpper ( os . Getenv ( EnvLog ) )
2016-03-14 17:17:05 +01:00
if envLevel == "" {
return ""
}
logLevel := "TRACE"
2015-10-01 21:45:12 +02:00
if isValidLogLevel ( envLevel ) {
2020-10-17 15:38:18 +02:00
logLevel = envLevel
2015-10-01 21:45:12 +02:00
} else {
log . Printf ( "[WARN] Invalid log level: %q. Defaulting to level: TRACE. Valid levels are: %+v" ,
2017-10-14 15:35:36 +02:00
envLevel , ValidLevels )
2015-10-01 21:45:12 +02:00
}
2019-12-05 20:49:11 +01:00
if logLevel != "TRACE" {
log . Printf ( "[WARN] Log levels other than TRACE are currently unreliable, and are supported only for backward compatibility.\n Use TF_LOG=TRACE to see Terraform's internal logs.\n ----" )
}
2015-10-01 21:45:12 +02:00
2016-03-14 17:17:05 +01:00
return logLevel
}
2015-10-01 21:45:12 +02:00
2016-03-14 17:17:05 +01:00
// IsDebugOrHigher returns whether or not the current log level is debug or trace
func IsDebugOrHigher ( ) bool {
2019-12-05 20:13:37 +01:00
level := string ( CurrentLogLevel ( ) )
2016-03-14 17:17:05 +01:00
return level == "DEBUG" || level == "TRACE"
2014-05-31 01:07:26 +02:00
}
2015-10-01 21:45:12 +02:00
func isValidLogLevel ( level string ) bool {
2017-10-14 15:35:36 +02:00
for _ , l := range ValidLevels {
2020-10-17 15:38:18 +02:00
if level == string ( l ) {
2015-10-01 21:45:12 +02:00
return true
}
}
return false
}