Skip to content

Commit

Permalink
Exposing log filtering on all offerings of this library
Browse files Browse the repository at this point in the history
- tflog root logger
- tflog subsystem logger
- tfsdklog root logger
- tfsdklog subsystem logger
  • Loading branch information
Ivan De Marino committed Jul 13, 2022
1 parent 82b4539 commit 8e9c63e
Show file tree
Hide file tree
Showing 8 changed files with 2,884 additions and 20 deletions.
194 changes: 189 additions & 5 deletions tflog/provider.go
Expand Up @@ -2,7 +2,9 @@ package tflog

import (
"context"
"regexp"

"github.com/hashicorp/go-hclog"
"github.com/hashicorp/terraform-plugin-log/internal/hclogutils"
"github.com/hashicorp/terraform-plugin-log/internal/logging"
)
Expand Down Expand Up @@ -36,7 +38,13 @@ func Trace(ctx context.Context, msg string, additionalFields ...map[string]inter
// so just making this a no-op is fine
return
}
logger.Trace(msg, hclogutils.MapsToArgs(additionalFields...)...)

additionalArgs, shouldOmit := omitOrMask(ctx, logger, &msg, additionalFields)
if shouldOmit {
return
}

logger.Trace(msg, additionalArgs...)
}

// Debug logs `msg` at the debug level to the logger in `ctx`, with optional
Expand All @@ -53,7 +61,13 @@ func Debug(ctx context.Context, msg string, additionalFields ...map[string]inter
// so just making this a no-op is fine
return
}
logger.Debug(msg, hclogutils.MapsToArgs(additionalFields...)...)

additionalArgs, shouldOmit := omitOrMask(ctx, logger, &msg, additionalFields)
if shouldOmit {
return
}

logger.Debug(msg, additionalArgs...)
}

// Info logs `msg` at the info level to the logger in `ctx`, with optional
Expand All @@ -70,7 +84,13 @@ func Info(ctx context.Context, msg string, additionalFields ...map[string]interf
// so just making this a no-op is fine
return
}
logger.Info(msg, hclogutils.MapsToArgs(additionalFields...)...)

additionalArgs, shouldOmit := omitOrMask(ctx, logger, &msg, additionalFields)
if shouldOmit {
return
}

logger.Info(msg, additionalArgs...)
}

// Warn logs `msg` at the warn level to the logger in `ctx`, with optional
Expand All @@ -87,7 +107,13 @@ func Warn(ctx context.Context, msg string, additionalFields ...map[string]interf
// so just making this a no-op is fine
return
}
logger.Warn(msg, hclogutils.MapsToArgs(additionalFields...)...)

additionalArgs, shouldOmit := omitOrMask(ctx, logger, &msg, additionalFields)
if shouldOmit {
return
}

logger.Warn(msg, additionalArgs...)
}

// Error logs `msg` at the error level to the logger in `ctx`, with optional
Expand All @@ -104,5 +130,163 @@ func Error(ctx context.Context, msg string, additionalFields ...map[string]inter
// so just making this a no-op is fine
return
}
logger.Error(msg, hclogutils.MapsToArgs(additionalFields...)...)

additionalArgs, shouldOmit := omitOrMask(ctx, logger, &msg, additionalFields)
if shouldOmit {
return
}

logger.Error(msg, additionalArgs...)
}

func omitOrMask(ctx context.Context, logger hclog.Logger, msg *string, additionalFields []map[string]interface{}) ([]interface{}, bool) {
tfLoggerOpts := logging.GetProviderRootTFLoggerOpts(ctx)
additionalArgs := hclogutils.MapsToArgs(additionalFields...)
impliedArgs := logger.ImpliedArgs()

// Apply the provider root LoggerOpts to determine if this log should be omitted
if tfLoggerOpts.ShouldOmit(msg, impliedArgs, additionalArgs) {
return nil, true
}

// Apply the provider root LoggerOpts to apply masking to this log
tfLoggerOpts.ApplyMask(msg, impliedArgs, additionalArgs)
return additionalArgs, false
}

// WithOmitLogWithFieldKeys returns a new context.Context that has a modified logger
// that will omit to write any log when any of the given keys is found
// within the arguments.
//
// Each call to this function is additive:
// the keys to omit by are added to the existing configuration.
//
// Example:
//
// configuration = `['foo', 'baz']`
//
// log1 = `{ msg = "...", args = { 'foo', '...', 'bar', '...' }` -> omitted
// log2 = `{ msg = "...", args = { 'bar', '...' }` -> printed
// log3 = `{ msg = "...", args = { 'baz`', '...', 'boo', '...' }` -> omitted
//
func WithOmitLogWithFieldKeys(ctx context.Context, keys ...string) context.Context {
lOpts := logging.GetProviderRootTFLoggerOpts(ctx)

lOpts = logging.WithOmitLogWithFieldKeys(keys...)(lOpts)

return logging.SetProviderRootTFLoggerOpts(ctx, lOpts)
}

// WithOmitLogWithMessageRegex returns a new context.Context that has a modified logger
// that will omit to write any log that has a message matching any of the
// given *regexp.Regexp.
//
// Each call to this function is additive:
// the regexp to omit by are added to the existing configuration.
//
// Example:
//
// configuration = `[regexp.MustCompile("(foo|bar)")]`
//
// log1 = `{ msg = "banana apple foo", args = {...}` -> omitted
// log2 = `{ msg = "pineapple mango", args = {...}` -> printed
// log3 = `{ msg = "pineapple mango bar", args = {...}` -> omitted
//
func WithOmitLogWithMessageRegex(ctx context.Context, expressions ...*regexp.Regexp) context.Context {
lOpts := logging.GetProviderRootTFLoggerOpts(ctx)

lOpts = logging.WithOmitLogWithMessageRegex(expressions...)(lOpts)

return logging.SetProviderRootTFLoggerOpts(ctx, lOpts)
}

// WithOmitLogMatchingString returns a new context.Context that has a modified logger
// that will omit to write any log that matches any of the given string.
//
// Each call to this function is additive:
// the string to omit by are added to the existing configuration.
//
// Example:
//
// configuration = `['foo', 'bar']`
//
// log1 = `{ msg = "banana apple foo", args = {...}` -> omitted
// log2 = `{ msg = "pineapple mango", args = {...}` -> printed
// log3 = `{ msg = "pineapple mango bar", args = {...}` -> omitted
//
func WithOmitLogMatchingString(ctx context.Context, matchingStrings ...string) context.Context {
lOpts := logging.GetProviderRootTFLoggerOpts(ctx)

lOpts = logging.WithOmitLogWithMessageStrings(matchingStrings...)(lOpts)

return logging.SetProviderRootTFLoggerOpts(ctx, lOpts)
}

// WithMaskFieldValueWithFieldKeys returns a new context.Context that has a modified logger
// that masks (replaces) with asterisks (`***`) any argument value where the
// key matches one of the given keys.
//
// Each call to this function is additive:
// the keys to mask by are added to the existing configuration.
//
// Example:
//
// configuration = `['foo', 'baz']`
//
// log1 = `{ msg = "...", args = { 'foo', '***', 'bar', '...' }` -> masked value
// log2 = `{ msg = "...", args = { 'bar', '...' }` -> as-is value
// log3 = `{ msg = "...", args = { 'baz`', '***', 'boo', '...' }` -> masked value
//
func WithMaskFieldValueWithFieldKeys(ctx context.Context, keys ...string) context.Context {
lOpts := logging.GetProviderRootTFLoggerOpts(ctx)

lOpts = logging.WithMaskFieldValueWithFieldKeys(keys...)(lOpts)

return logging.SetProviderRootTFLoggerOpts(ctx, lOpts)
}

// WithMaskMessageRegex returns a new context.Context that has a modified logger
// that masks (replaces) with asterisks (`***`) all message substrings matching one
// of the given strings.
//
// Each call to this function is additive:
// the regexp to mask by are added to the existing configuration.
//
// Example:
//
// configuration = `[regexp.MustCompile("(foo|bar)")]`
//
// log1 = `{ msg = "banana apple ***", args = {...}` -> masked portion
// log2 = `{ msg = "pineapple mango", args = {...}` -> as-is
// log3 = `{ msg = "pineapple mango ***", args = {...}` -> masked portion
//
func WithMaskMessageRegex(ctx context.Context, expressions ...*regexp.Regexp) context.Context {
lOpts := logging.GetProviderRootTFLoggerOpts(ctx)

lOpts = logging.WithMaskMessageRegex(expressions...)(lOpts)

return logging.SetProviderRootTFLoggerOpts(ctx, lOpts)
}

// WithMaskLogMatchingString returns a new context.Context that has a modified logger
// that masks (replace) with asterisks (`***`) all message substrings equal to one
// of the given strings.
//
// Each call to this function is additive:
// the string to mask by are added to the existing configuration.
//
// Example:
//
// configuration = `['foo', 'bar']`
//
// log1 = `{ msg = "banana apple ***", args = {...}` -> masked portion
// log2 = `{ msg = "pineapple mango", args = {...}` -> as-is
// log3 = `{ msg = "pineapple mango ***", args = {...}` -> masked portion
//
func WithMaskLogMatchingString(ctx context.Context, matchingStrings ...string) context.Context {
lOpts := logging.GetProviderRootTFLoggerOpts(ctx)

lOpts = logging.WithMaskMessageStrings(matchingStrings...)(lOpts)

return logging.SetProviderRootTFLoggerOpts(ctx, lOpts)
}

0 comments on commit 8e9c63e

Please sign in to comment.