Terraformで出力ログレベルを変更するやり方の備忘録です。
- はじめに
- TerraformでDEBUGレベルのログを出力する
- TerraformとProviderで個別にログの出力レベルを設定する
- おまけ: Terraformのソースコードを読む
- おわりに
- 参考
はじめに
こんにちは、@bioerrorlogです。
不具合の切り分けをする際、ログは重要な情報源です。
そして十分な情報がログから得られない場合は、ログの出力レベルを上げてログ出力量を増やすのも有効です。
今回は、Terraformでログの出力レベルを変更する方法を備忘にまとめつつ、ついでにソースコードにも目を通してみます。
TerraformでDEBUGレベルのログを出力する
Terraformでログの出力レベルを変更するには、環境変数TF_LOG
を設定します。
ドキュメントはこちら: Debugging | Terraform by HashiCorp
例えばterraform plan
でDEBUGレベルのログを出力するには、環境変数TF_LOG
をDEBUG
に設定します。
# コマンド一回限りでTF_LOGを設定する場合 TF_LOG=DEBUG terraform plan # TF_LOGを設定した上でコマンド実行する場合 export TF_LOG=DEBUG terraform plan
TF_LOG
に設定できるログレベルは下記の5つです。
TRACE
DEBUG
INFO
WARN
ERROR
必要な情報量に応じて使い分けましょう。
TerraformとProviderで個別にログの出力レベルを設定する
TerraformそのものとProviderで別々にログレベルを設定することもできます。
Terraformそのもののログレベルを設定するには環境変数TF_LOG_CORE
を、
Providerのログレベルを設定するには環境変数TF_LOG_PROVIDER
を利用します。
# TerraformそのもののログレベルをDEBUGに設定してplan実行 TF_LOG_CORE=DEBUG terraform plan # ProviderのログレベルをDEBUGに設定してplan実行 TF_LOG_PROVIDER=DEBUG terraform plan
TF_LOG_CORE
TF_LOG_PROVIDER
ともに、設定できるレベルはTF_LOG
と同じです:
TRACE
DEBUG
INFO
WARN
ERROR
おまけ: Terraformのソースコードを読む
せっかくなので、Terraformのログレベルを設定している部分のソースコードにも目を通してみます。
// newHCLogger returns a new hclog.Logger instance with the given name func newHCLogger(name string) hclog.Logger { logOutput := io.Writer(os.Stderr) logLevel, json := globalLogLevel() if logPath := os.Getenv(envLogFile); logPath != "" { f, err := os.OpenFile(logPath, syscall.O_CREAT|syscall.O_RDWR|syscall.O_APPEND, 0666) if err != nil { fmt.Fprintf(os.Stderr, "Error opening log file: %v\n", err) } else { logOutput = f } } return hclog.NewInterceptLogger(&hclog.LoggerOptions{ Name: name, Level: logLevel, Output: logOutput, IndependentLevels: true, JSONFormat: json, }) } // NewLogger returns a new logger based in the current global logger, with the // given name appended. func NewLogger(name string) hclog.Logger { if name == "" { panic("logger name required") } return &logPanicWrapper{ Logger: logger.Named(name), } } // NewProviderLogger returns a logger for the provider plugin, possibly with a // different log level from the global logger. func NewProviderLogger(prefix string) hclog.Logger { l := &logPanicWrapper{ Logger: logger.Named(prefix + "provider"), } level := providerLogLevel() logger.Debug("created provider logger", "level", level) l.SetLevel(level) return l } // CurrentLogLevel returns the current log level string based the environment vars func CurrentLogLevel() string { ll, _ := globalLogLevel() return strings.ToUpper(ll.String()) } func providerLogLevel() hclog.Level { providerEnvLevel := strings.ToUpper(os.Getenv(envLogProvider)) if providerEnvLevel == "" { providerEnvLevel = strings.ToUpper(os.Getenv(envLog)) } return parseLogLevel(providerEnvLevel) } func globalLogLevel() (hclog.Level, bool) { var json bool envLevel := strings.ToUpper(os.Getenv(envLog)) if envLevel == "" { envLevel = strings.ToUpper(os.Getenv(envLogCore)) } if envLevel == "JSON" { json = true } return parseLogLevel(envLevel), json }
GlobalなログレベルはglobalLogLevel
で取得してnewHCLogger
時に設定、ProviderのログレベルはproviderLogLevel
で取得してNewProviderLogger
で設定されているのが分かります。
ログレベルとして受け取り可能な値はここで指定されています:
// ValidLevels are the log level names that Terraform recognizes. ValidLevels = []string{"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF"}
terraform/logging.go at c047958b5708e4f500fe61000a662c169d048fff · hashicorp/terraform · GitHub
ちなみにログレベルの値の解釈時にはstrings.ToUpper
で包まれているので、大文字/小文字は影響ないようです。
おわりに
以上、Terraformで出力ログレベルを変更するやり方をまとめました。
ちょっと覚えておくだけでも対応スピードが上がるので、こういった引き出しも増やしていきたいものです。
[関連記事]
参考
Debugging | Terraform by HashiCorp
terraform/logging.go at 271352620b43872aa99f7837f9c1c243b417a45c · hashicorp/terraform · GitHub