use a single log writer

Use a single log writer instance for all std library logging.

Setup the std log writer in the logging package, and remove boilerplate
from test packages.
This commit is contained in:
James Bardin 2020-10-18 10:01:48 -04:00
parent abf6b9b378
commit 0b31ffa587
16 changed files with 37 additions and 146 deletions

View File

@ -2,24 +2,13 @@ package local
import ( import (
"flag" "flag"
"io/ioutil"
"log"
"os" "os"
"testing" "testing"
"github.com/hashicorp/terraform/internal/logging" _ "github.com/hashicorp/terraform/internal/logging"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
os.Exit(m.Run()) os.Exit(m.Run())
} }

View File

@ -2,30 +2,20 @@ package inmem
import ( import (
"flag" "flag"
"io/ioutil"
"log"
"os" "os"
"testing" "testing"
"github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/internal/logging"
statespkg "github.com/hashicorp/terraform/states" statespkg "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/states/remote" "github.com/hashicorp/terraform/states/remote"
_ "github.com/hashicorp/terraform/internal/logging"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
os.Exit(m.Run()) os.Exit(m.Run())
} }

View File

@ -2,25 +2,15 @@ package remote
import ( import (
"flag" "flag"
"io/ioutil"
"log"
"os" "os"
"testing" "testing"
"github.com/hashicorp/terraform/internal/logging" _ "github.com/hashicorp/terraform/internal/logging"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
// Make sure TF_FORCE_LOCAL_BACKEND is unset // Make sure TF_FORCE_LOCAL_BACKEND is unset
os.Unsetenv("TF_FORCE_LOCAL_BACKEND") os.Unsetenv("TF_FORCE_LOCAL_BACKEND")

View File

@ -5,11 +5,9 @@ import (
"crypto/md5" "crypto/md5"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"flag"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
@ -30,7 +28,6 @@ import (
"github.com/hashicorp/terraform/configs/configload" "github.com/hashicorp/terraform/configs/configload"
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/internal/copy" "github.com/hashicorp/terraform/internal/copy"
"github.com/hashicorp/terraform/internal/logging"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/plans/planfile" "github.com/hashicorp/terraform/plans/planfile"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
@ -44,6 +41,7 @@ import (
backendInit "github.com/hashicorp/terraform/backend/init" backendInit "github.com/hashicorp/terraform/backend/init"
backendLocal "github.com/hashicorp/terraform/backend/local" backendLocal "github.com/hashicorp/terraform/backend/local"
_ "github.com/hashicorp/terraform/internal/logging"
) )
// These are the directories for our test data and fixtures. // These are the directories for our test data and fixtures.
@ -83,15 +81,6 @@ func init() {
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
defer os.RemoveAll(testingDir) defer os.RemoveAll(testingDir)
flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
// Make sure backend init is initialized, since our tests tend to assume it. // Make sure backend init is initialized, since our tests tend to assume it.
backendInit.Init(nil) backendInit.Init(nil)

View File

@ -3,8 +3,6 @@ package dag
import ( import (
"flag" "flag"
"fmt" "fmt"
"io/ioutil"
"log"
"os" "os"
"reflect" "reflect"
"strconv" "strconv"
@ -14,19 +12,11 @@ import (
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
"github.com/hashicorp/terraform/internal/logging" _ "github.com/hashicorp/terraform/internal/logging"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
os.Exit(m.Run()) os.Exit(m.Run())
} }

View File

@ -383,7 +383,6 @@ func (w *Walker) walkVertex(v Vertex, info *walkerVertex) {
var diags tfdiags.Diagnostics var diags tfdiags.Diagnostics
var upstreamFailed bool var upstreamFailed bool
if depsSuccess { if depsSuccess {
log.Printf("[TRACE] dag/walk: visiting %q", VertexName(v))
diags = w.Callback(v) diags = w.Callback(v)
} else { } else {
log.Printf("[TRACE] dag/walk: upstream of %q errored, so skipping", VertexName(v)) log.Printf("[TRACE] dag/walk: upstream of %q errored, so skipping", VertexName(v))

View File

@ -68,11 +68,7 @@ func newHTTPMirrorSourceWithHTTPClient(baseURL *url.URL, creds svcauth.Credentia
retryableClient.RequestLogHook = requestLogHook retryableClient.RequestLogHook = requestLogHook
retryableClient.ErrorHandler = maxRetryErrorHandler retryableClient.ErrorHandler = maxRetryErrorHandler
logOutput, err := logging.LogOutput() retryableClient.Logger = log.New(logging.LogOutput(), "", log.Flags())
if err != nil {
log.Printf("[WARN] Failed to set up provider HTTP mirror logger, so continuing without client logging: %s", err)
}
retryableClient.Logger = log.New(logOutput, "", log.Flags())
return &HTTPMirrorSource{ return &HTTPMirrorSource{
baseURL: baseURL, baseURL: baseURL,

View File

@ -77,12 +77,7 @@ func newRegistryClient(baseURL *url.URL, creds svcauth.HostCredentials) *registr
retryableClient.RequestLogHook = requestLogHook retryableClient.RequestLogHook = requestLogHook
retryableClient.ErrorHandler = maxRetryErrorHandler retryableClient.ErrorHandler = maxRetryErrorHandler
logOutput, err := logging.LogOutput() retryableClient.Logger = log.New(logging.LogOutput(), "", log.Flags())
if err != nil {
log.Printf("[WARN] Failed to set up registry client logger, "+
"continuing without client logging: %s", err)
}
retryableClient.Logger = log.New(logOutput, "", log.Flags())
return &registryClient{ return &registryClient{
baseURL: baseURL, baseURL: baseURL,

View File

@ -4,7 +4,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -15,21 +14,14 @@ import (
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/configs/configload" "github.com/hashicorp/terraform/configs/configload"
"github.com/hashicorp/terraform/internal/copy" "github.com/hashicorp/terraform/internal/copy"
"github.com/hashicorp/terraform/internal/logging"
"github.com/hashicorp/terraform/registry" "github.com/hashicorp/terraform/registry"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
_ "github.com/hashicorp/terraform/internal/logging"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
os.Exit(m.Run()) os.Exit(m.Run())
} }

View File

@ -25,16 +25,25 @@ var ValidLevels = []LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERROR"}
// logger is the global hclog logger // logger is the global hclog logger
var logger hclog.Logger var logger hclog.Logger
// logWriter is a global writer for logs, to be used with the std log package
var logWriter io.Writer
func init() { func init() {
logger = NewHCLogger("") logger = NewHCLogger("")
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)
} }
// LogOutput determines where we should send logs (if anywhere) and the log level. // LogOutput return the default global log io.Writer
func LogOutput() (logOutput io.Writer, err error) { func LogOutput() io.Writer {
return logger.StandardWriter(&hclog.StandardLoggerOptions{InferLevels: true}), nil return logWriter
} }
// HCLogger returns the default global loggers // HCLogger returns the default global hclog logger
func HCLogger() hclog.Logger { func HCLogger() hclog.Logger {
return logger return logger
} }
@ -63,25 +72,6 @@ func NewHCLogger(name string) hclog.Logger {
}) })
} }
// SetOutput checks for a log destination with LogOutput, and calls
// log.SetOutput with the result. If LogOutput returns nil, SetOutput uses
// ioutil.Discard. Any error from LogOutout is fatal.
func SetOutput() {
out, err := LogOutput()
if err != nil {
log.Fatal(err)
}
if out == nil {
out = ioutil.Discard
}
// the hclog logger will add the prefix info
log.SetFlags(0)
log.SetPrefix("")
log.SetOutput(out)
}
// CurrentLogLevel returns the current log level string based the environment vars // CurrentLogLevel returns the current log level string based the environment vars
func CurrentLogLevel() string { func CurrentLogLevel() string {
envLevel := strings.ToUpper(os.Getenv(EnvLog)) envLevel := strings.ToUpper(os.Getenv(EnvLog))

View File

@ -87,11 +87,7 @@ func NewClient(services *disco.Disco, client *http.Client) *Client {
retryableClient.RequestLogHook = requestLogHook retryableClient.RequestLogHook = requestLogHook
retryableClient.ErrorHandler = maxRetryErrorHandler retryableClient.ErrorHandler = maxRetryErrorHandler
logOutput, err := logging.LogOutput() logOutput := logging.LogOutput()
if err != nil {
log.Printf("[WARN] Failed to set up registry client logger, "+
"continuing without client logging: %s", err)
}
retryableClient.Logger = log.New(logOutput, "", log.Flags()) retryableClient.Logger = log.New(logOutput, "", log.Flags())
services.Transport = retryableClient.HTTPClient.Transport services.Transport = retryableClient.HTTPClient.Transport

View File

@ -2,8 +2,6 @@ package repl
import ( import (
"flag" "flag"
"io/ioutil"
"log"
"os" "os"
"strings" "strings"
"testing" "testing"
@ -13,23 +11,15 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/internal/initwd" "github.com/hashicorp/terraform/internal/initwd"
"github.com/hashicorp/terraform/internal/logging"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
_ "github.com/hashicorp/terraform/internal/logging"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
os.Exit(m.Run()) os.Exit(m.Run())
} }

View File

@ -4,13 +4,11 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"flag" "flag"
"io/ioutil"
"log"
"os" "os"
"testing" "testing"
"time" "time"
"github.com/hashicorp/terraform/internal/logging" _ "github.com/hashicorp/terraform/internal/logging"
) )
func TestNewLockInfo(t *testing.T) { func TestNewLockInfo(t *testing.T) {
@ -91,12 +89,5 @@ func TestLockWithContext(t *testing.T) {
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
os.Exit(m.Run()) os.Exit(m.Run())
} }

View File

@ -10,7 +10,6 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/instances" "github.com/hashicorp/terraform/instances"
"github.com/hashicorp/terraform/internal/logging"
"github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/lang"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
@ -19,11 +18,9 @@ import (
"github.com/hashicorp/terraform/states/statefile" "github.com/hashicorp/terraform/states/statefile"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
)
func init() { _ "github.com/hashicorp/terraform/internal/logging"
logging.SetOutput() )
}
// InputMode defines what sort of input will be asked for when Input // InputMode defines what sort of input will be asked for when Input
// is called on Context. // is called on Context.

View File

@ -2,6 +2,7 @@ package terraform
import ( import (
"log" "log"
"strings"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
@ -77,7 +78,11 @@ func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics {
subDiags := g.walk(walker) subDiags := g.walk(walker)
diags = diags.Append(subDiags) diags = diags.Append(subDiags)
if subDiags.HasErrors() { if subDiags.HasErrors() {
log.Printf("[TRACE] vertex %q: dynamic subgraph encountered errors", dag.VertexName(v)) var errs []string
for _, d := range subDiags {
errs = append(errs, d.Description().Summary)
}
log.Printf("[TRACE] vertex %q: dynamic subgraph encountered errors: %s", dag.VertexName(v), strings.Join(errs, ","))
return return
} }
log.Printf("[TRACE] vertex %q: dynamic subgraph completed successfully", dag.VertexName(v)) log.Printf("[TRACE] vertex %q: dynamic subgraph completed successfully", dag.VertexName(v))

View File

@ -4,7 +4,6 @@ import (
"flag" "flag"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -20,12 +19,13 @@ import (
"github.com/hashicorp/terraform/configs/configload" "github.com/hashicorp/terraform/configs/configload"
"github.com/hashicorp/terraform/helper/experiment" "github.com/hashicorp/terraform/helper/experiment"
"github.com/hashicorp/terraform/internal/initwd" "github.com/hashicorp/terraform/internal/initwd"
"github.com/hashicorp/terraform/internal/logging"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/provisioners"
"github.com/hashicorp/terraform/registry" "github.com/hashicorp/terraform/registry"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
_ "github.com/hashicorp/terraform/internal/logging"
) )
// This is the directory where our test fixtures are. // This is the directory where our test fixtures are.
@ -39,14 +39,6 @@ func TestMain(m *testing.M) {
experiment.Flag(flag.CommandLine) experiment.Flag(flag.CommandLine)
flag.Parse() flag.Parse()
if testing.Verbose() {
// if we're verbose, use the logging requested by TF_LOG
logging.SetOutput()
} else {
// otherwise silence all logs
log.SetOutput(ioutil.Discard)
}
// Make sure shadow operations fail our real tests // Make sure shadow operations fail our real tests
contextFailOnShadowError = true contextFailOnShadowError = true