Skip to content

Commit

Permalink
Custom Log Formatting (#3537)
Browse files Browse the repository at this point in the history
* feat: custom log format implementation

* chore: remove old code

* chore: add presets

* chore: fix lint

* chore: fix tests

* chore: fix tests

* chore: fix tests

* chore: code improvements

* chore: code improvements

* chore: rename flag

* chore: deprecated flags

* chore: add tests, strict control

* chore: fix test

* chore: fix exit code message

* chore: code improvements

* chore: fix lint

* chore: fix grammar

* chore: code comment

* chore: update docs

* chore: code improvements, doc update

* chore: fix tests

* chore: doc update

* Apply suggestions from code review

Co-authored-by: Yousif Akbar <[email protected]>

* chore: doc update

* chore: doc update

* chore: doc update

* chore: doc update

* chore: fixes after reviewing

---------

Co-authored-by: Yousif Akbar <[email protected]>
  • Loading branch information
levkohimins and yhakbar authored Nov 18, 2024
1 parent 8bfe94e commit d8adfda
Show file tree
Hide file tree
Showing 52 changed files with 2,411 additions and 815 deletions.
17 changes: 7 additions & 10 deletions cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ import (
"github.com/gruntwork-io/terragrunt/engine"
"github.com/gruntwork-io/terragrunt/internal/os/exec"
"github.com/gruntwork-io/terragrunt/internal/os/signal"
"github.com/gruntwork-io/terragrunt/pkg/log"
"github.com/gruntwork-io/terragrunt/pkg/log/format"
"github.com/gruntwork-io/terragrunt/pkg/log/hooks"
"github.com/gruntwork-io/terragrunt/telemetry"
"github.com/gruntwork-io/terragrunt/terraform"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -47,6 +44,7 @@ import (
validateinputs "github.com/gruntwork-io/terragrunt/cli/commands/validate-inputs"
"github.com/gruntwork-io/terragrunt/options"
"github.com/gruntwork-io/terragrunt/pkg/cli"
"github.com/gruntwork-io/terragrunt/pkg/log/format/placeholders"
)

func init() {
Expand Down Expand Up @@ -294,17 +292,16 @@ func initialSetup(cliCtx *cli.Context, opts *options.TerragruntOptions) error {
return errors.New(err)
}

opts.Logger = opts.Logger.WithField(format.PrefixKeyName, workingDir)
opts.Logger = opts.Logger.WithField(placeholders.WorkDirKeyName, workingDir)

opts.RootWorkingDir = filepath.ToSlash(workingDir)

if !opts.LogShowAbsPaths {
hook, err := hooks.NewRelativePathHook(opts.RootWorkingDir)
if err != nil {
return err
}
if err := opts.LogFormatter.SetBaseDir(opts.RootWorkingDir); err != nil {
return err
}

opts.Logger.SetOptions(log.WithHooks(hook))
if opts.LogShowAbsPaths {
opts.LogFormatter.DisableRelativePaths()
}

// --- Download Dir
Expand Down
93 changes: 57 additions & 36 deletions cli/commands/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,12 @@ import (
"github.com/gruntwork-io/terragrunt/pkg/cli"
"github.com/gruntwork-io/terragrunt/pkg/log"
"github.com/gruntwork-io/terragrunt/pkg/log/format"
"github.com/gruntwork-io/terragrunt/pkg/log/format/placeholders"
"github.com/gruntwork-io/terragrunt/shell"
"github.com/gruntwork-io/terragrunt/util"
)

const (
TerragruntDisableLogFormattingFlagName = "terragrunt-disable-log-formatting"
TerragruntDisableLogFormattingEnvName = "TERRAGRUNT_DISABLE_LOG_FORMATTING"

TerragruntJSONLogFlagName = "terragrunt-json-log"
TerragruntJSONLogEnvName = "TERRAGRUNT_JSON_LOG"

TerragruntConfigFlagName = "terragrunt-config"
TerragruntConfigEnvName = "TERRAGRUNT_CONFIG"

Expand Down Expand Up @@ -152,8 +147,13 @@ const (
TerragruntForwardTFStdoutFlagName = "terragrunt-forward-tf-stdout"
TerragruntForwardTFStdoutEnvName = "TERRAGRUNT_FORWARD_TF_STDOUT"

// Strict Mode related flags/envs
TerragruntLogFormatFlagName = "terragrunt-log-format"
TerragruntLogFormatEnvName = "TERRAGRUNT_LOG_FORMAT"

TerragruntLogCustomFormatFlagName = "terragrunt-log-custom-format"
TerragruntLogCustomFormatEnvName = "TERRAGRUNT_LOG_CUSTOM_FORMAT"

// Strict Mode related flags/envs
TerragruntStrictModeFlagName = "strict-mode"
TerragruntStrictModeEnvName = "TERRAGRUNT_STRICT_MODE"

Expand Down Expand Up @@ -350,7 +350,7 @@ func NewGlobalFlags(opts *options.TerragruntOptions) cli.Flags {
EnvVar: TerragruntLogLevelEnvName,
DefaultText: opts.LogLevel.String(),
Usage: fmt.Sprintf("Sets the logging level for Terragrunt. Supported levels: %s", log.AllLevels),
Action: func(ctx *cli.Context, val string) error {
Action: func(_ *cli.Context, val string) error {
// Before the release of v0.67.0, these levels actually disabled logs, since we do not use these levels for logging.
// For backward compatibility we simulate the same behavior.
removedLevels := []string{
Expand All @@ -360,49 +360,28 @@ func NewGlobalFlags(opts *options.TerragruntOptions) cli.Flags {

if collections.ListContainsElement(removedLevels, val) {
opts.ForwardTFStdout = true
opts.Logger.SetOptions(log.WithFormatter(&format.SilentFormatter{}))
opts.LogFormatter.SetFormat(nil)
return nil
}

level, err := log.ParseLevel(val)
if err != nil {
return errors.Errorf("flag --%s, %w", TerragruntLogLevelFlagName, err)
return cli.NewExitError(errors.Errorf("flag --%s, %w", TerragruntLogLevelFlagName, err), 1)
}

opts.Logger.SetOptions(log.WithLevel(level))
opts.LogLevel = level
return nil

},
},
&cli.BoolFlag{
Name: TerragruntLogDisableFlagName,
EnvVar: TerragruntLogDisableEnvName,
Usage: "Disable logging",
Destination: &opts.DisableLog,
Action: func(ctx *cli.Context, _ bool) error {
Action: func(_ *cli.Context, _ bool) error {
opts.ForwardTFStdout = true
opts.Logger.SetOptions(log.WithFormatter(&format.SilentFormatter{}))
return nil
},
},
&cli.BoolFlag{
Name: TerragruntDisableLogFormattingFlagName,
EnvVar: TerragruntDisableLogFormattingEnvName,
Destination: &opts.DisableLogFormatting,
Usage: "If specified, logs will be displayed in key/value format. By default, logs are formatted in a human readable format.",
Action: func(ctx *cli.Context, val bool) error {
opts.LogFormatter.DisableLogFormatting = val
return nil
},
},
&cli.BoolFlag{
Name: TerragruntJSONLogFlagName,
EnvVar: TerragruntJSONLogEnvName,
Destination: &opts.JSONLogFormat,
Usage: "If specified, Terragrunt will output its logs in JSON format.",
Action: func(ctx *cli.Context, _ bool) error {
opts.Logger.SetOptions(log.WithFormatter(&format.JSONFormatter{}))
opts.LogFormatter.SetFormat(nil)
return nil
},
},
Expand All @@ -417,8 +396,8 @@ func NewGlobalFlags(opts *options.TerragruntOptions) cli.Flags {
EnvVar: TerragruntNoColorEnvName,
Destination: &opts.DisableLogColors,
Usage: "If specified, Terragrunt output won't contain any color.",
Action: func(ctx *cli.Context, val bool) error {
opts.LogFormatter.DisableColors = val
Action: func(_ *cli.Context, _ bool) error {
opts.LogFormatter.DisableColors()
return nil
},
},
Expand Down Expand Up @@ -446,6 +425,44 @@ func NewGlobalFlags(opts *options.TerragruntOptions) cli.Flags {
Destination: &opts.ForwardTFStdout,
Usage: "If specified, the output of OpenTofu/Terraform commands will be printed as is, without being integrated into the Terragrunt log.",
},
&cli.GenericFlag[string]{
Name: TerragruntLogFormatFlagName,
EnvVar: TerragruntLogFormatEnvName,
Usage: "Set the log format",
Action: func(_ *cli.Context, val string) error {
phs, err := format.ParseFormat(val)
if err != nil {
return cli.NewExitError(errors.Errorf("flag --%s, invalid format %q, %v", TerragruntLogFormatFlagName, val, err), 1)
}

if opts.DisableLog || opts.DisableLogFormatting || opts.JSONLogFormat {
return nil
}

if val == format.BareFormatName {
opts.ForwardTFStdout = true
}

opts.LogFormatter.SetFormat(phs)

return nil
},
},
&cli.GenericFlag[string]{
Name: TerragruntLogCustomFormatFlagName,
EnvVar: TerragruntLogCustomFormatEnvName,
Usage: "Set the custom log formatting",
Action: func(_ *cli.Context, val string) error {
phs, err := placeholders.Parse(val)
if err != nil {
return cli.NewExitError(errors.Errorf("flag --%s, %w", TerragruntLogCustomFormatFlagName, err), 1)
}

opts.LogFormatter.SetFormat(phs)

return nil
},
},
&cli.BoolFlag{
Name: TerragruntStrictIncludeFlagName,
EnvVar: TerragruntStrictIncludeEnvName,
Expand Down Expand Up @@ -501,7 +518,11 @@ func NewGlobalFlags(opts *options.TerragruntOptions) cli.Flags {
Destination: &opts.StrictControls,
Usage: "Enables specific strict controls. For a list of available controls, see https://terragrunt.gruntwork.io/docs/reference/strict-mode .",
Action: func(ctx *cli.Context, val []string) error {
return strict.StrictControls.ValidateControlNames(val)
if err := strict.StrictControls.ValidateControlNames(val); err != nil {
return cli.NewExitError(err, 1)
}

return nil
},
},
// Terragrunt Provider Cache flags
Expand Down
48 changes: 48 additions & 0 deletions cli/deprecated_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@ package cli

import (
"github.com/gruntwork-io/terragrunt/cli/commands"
"github.com/gruntwork-io/terragrunt/internal/strict"
"github.com/gruntwork-io/terragrunt/options"
"github.com/gruntwork-io/terragrunt/pkg/cli"
"github.com/gruntwork-io/terragrunt/pkg/log/format"
)

// The following flags are DEPRECATED
const (
TerragruntIncludeModulePrefixFlagName = "terragrunt-include-module-prefix"
TerragruntIncludeModulePrefixEnvName = "TERRAGRUNT_INCLUDE_MODULE_PREFIX"

TerragruntDisableLogFormattingFlagName = "terragrunt-disable-log-formatting"
TerragruntDisableLogFormattingEnvName = "TERRAGRUNT_DISABLE_LOG_FORMATTING"

TerragruntJSONLogFlagName = "terragrunt-json-log"
TerragruntJSONLogEnvName = "TERRAGRUNT_JSON_LOG"
)

// NewDeprecatedFlags creates and returns deprecated flags.
Expand All @@ -26,6 +34,46 @@ func NewDeprecatedFlags(opts *options.TerragruntOptions) cli.Flags {
return nil
},
},
&cli.BoolFlag{
Name: TerragruntDisableLogFormattingFlagName,
EnvVar: TerragruntDisableLogFormattingEnvName,
Destination: &opts.DisableLogFormatting,
Usage: "If specified, logs will be displayed in key/value format. By default, logs are formatted in a human readable format.",
Action: func(_ *cli.Context, _ bool) error {
opts.LogFormatter.SetFormat(format.NewKeyValueFormat())

if control, ok := strict.GetStrictControl(strict.DisableLogFormatting); ok {
warn, err := control.Evaluate(opts)
if err != nil {
return err
}

opts.Logger.Warnf(warn)
}

return nil
},
},
&cli.BoolFlag{
Name: TerragruntJSONLogFlagName,
EnvVar: TerragruntJSONLogEnvName,
Destination: &opts.JSONLogFormat,
Usage: "If specified, Terragrunt will output its logs in JSON format.",
Action: func(_ *cli.Context, _ bool) error {
opts.LogFormatter.SetFormat(format.NewJSONFormat())

if control, ok := strict.GetStrictControl(strict.JSONLog); ok {
warn, err := control.Evaluate(opts)
if err != nil {
return err
}

opts.Logger.Warnf(warn)
}

return nil
},
},
}

return flags
Expand Down
12 changes: 11 additions & 1 deletion cli/provider_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,18 @@ func (cache *ProviderCache) TerraformCommandHook(
// To prevent a loop
ctx = shell.ContextWithTerraformCommandHook(ctx, nil)

cliConfigFilename := filepath.Join(opts.WorkingDir, localCLIFilename)

if !filepath.IsAbs(cliConfigFilename) {
absPath, err := filepath.Abs(cliConfigFilename)
if err != nil {
return nil, errors.New(err)
}

cliConfigFilename = absPath
}

var (
cliConfigFilename = filepath.Join(opts.WorkingDir, localCLIFilename)
env = providerCacheEnvironment(opts, cliConfigFilename)
skipRunTargetCommand bool
)
Expand Down
5 changes: 2 additions & 3 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ import (
)

func createLogger() log.Logger {
formatter := format.NewFormatter()
formatter.DisableColors = true
formatter.DisableLogFormatting = true
formatter := format.NewFormatter(format.NewKeyValueFormat())
formatter.DisableColors()

return log.New(log.WithLevel(log.DebugLevel), log.WithFormatter(formatter))
}
Expand Down
5 changes: 2 additions & 3 deletions configstack/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ func TestLogReductionHook(t *testing.T) {

stdout := bytes.Buffer{}

formatter := format.NewFormatter()
formatter.DisableColors = true
formatter.DisableLogFormatting = true
formatter := format.NewFormatter(format.NewKeyValueFormat())
formatter.DisableColors()

var testLogger = log.New(
log.WithOutput(&stdout),
Expand Down
Loading

0 comments on commit d8adfda

Please sign in to comment.