pulumi/sdk/go/common/util/logging/log.go

203 lines
5.5 KiB
Go
Raw Permalink Normal View History

2018-05-22 19:43:36 +00:00
// Copyright 2016-2018, Pulumi Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logging
// Wrapper around the glog API that allows us to intercept all logging calls and manipulate them as
// necessary. This is primarily used so we can make a best effort approach to filtering out secrets
// from any logs we emit before they get written to log-files/stderr.
//
// Code in pulumi should use this package instead of directly importing glog itself. If any glog
// methods are needed that are not exported from this, they can be added, with the caveat that they
// should be updated to properly filter as well before forwarding things along.
import (
"encoding/json"
"flag"
"fmt"
"strconv"
2019-08-14 13:20:56 +00:00
"strings"
"sync"
"github.com/golang/glog"
"github.com/pulumi/pulumi/sdk/v3/go/common/slice"
)
type Filter interface {
Filter(s string) string
}
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
var (
LogToStderr = false // true if logging is being redirected to stderr.
Verbose = 0 // >0 if verbose logging is enabled at a particular level.
LogFlow = false // true to flow logging settings to child processes.
)
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
var (
rwLock sync.RWMutex
filters []Filter
)
// VerboseLogger logs messages only if verbosity matches the level it was built with.
//
// It may be used as a boolean to check if it's enabled.
//
// if log := logging.V(lvl); log {
// log.Infoln(expensiveComputation())
// }
type VerboseLogger glog.Verbose
// Info is equivalent to the global Info function, guarded by the value of v.
// See the documentation of V for usage.
func (v VerboseLogger) Info(args ...interface{}) {
if v {
Use the Depth variants in glog calls (#15307) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description This allows pulumi's log output to contain the location of where the log call was made from, rather than it always reporting the line in `log.go` where the glog call was made. <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This changes ``` I0124 20:53:35.244319 169013 log.go:81] skipping update check I0124 20:53:36.262079 169013 log.go:81] found username for access token ``` to ``` I0129 14:08:42.918230 38925 pulumi.go:231] skipping update check I0129 14:08:45.056866 38925 backend.go:615] found username for access token ``` ## Checklist - [X] I have run `make tidy` to update any new dependencies - [X] I have run `make lint` to verify my code passes the lint check - [X] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works - This is hard to test because it is difficult to reliably intercept stderr from within go tests <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> Co-authored-by: Paul Roberts <proberts@pulumi.com>
2024-01-29 22:51:45 +00:00
glog.Verbose(v).InfoDepth(1, FilterString(fmt.Sprint(args...)))
}
}
// Infoln is equivalent to the global Infoln function, guarded by the value of v.
// See the documentation of V for usage.
func (v VerboseLogger) Infoln(args ...interface{}) {
if v {
glog.Verbose(v).Infoln(FilterString(fmt.Sprint(args...)))
}
}
// Infof is equivalent to the global Infof function, guarded by the value of v.
// See the documentation of V for usage.
func (v VerboseLogger) Infof(format string, args ...interface{}) {
if v {
Use the Depth variants in glog calls (#15307) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description This allows pulumi's log output to contain the location of where the log call was made from, rather than it always reporting the line in `log.go` where the glog call was made. <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This changes ``` I0124 20:53:35.244319 169013 log.go:81] skipping update check I0124 20:53:36.262079 169013 log.go:81] found username for access token ``` to ``` I0129 14:08:42.918230 38925 pulumi.go:231] skipping update check I0129 14:08:45.056866 38925 backend.go:615] found username for access token ``` ## Checklist - [X] I have run `make tidy` to update any new dependencies - [X] I have run `make lint` to verify my code passes the lint check - [X] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works - This is hard to test because it is difficult to reliably intercept stderr from within go tests <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> Co-authored-by: Paul Roberts <proberts@pulumi.com>
2024-01-29 22:51:45 +00:00
glog.Verbose(v).InfoDepthf(1, "%s", FilterString(fmt.Sprintf(format, args...)))
}
}
// V builds a logger that logs messages only if verbosity is at least at the provided level.
func V(level glog.Level) VerboseLogger {
return VerboseLogger(glog.V(level))
}
func Errorf(format string, args ...interface{}) {
Use the Depth variants in glog calls (#15307) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description This allows pulumi's log output to contain the location of where the log call was made from, rather than it always reporting the line in `log.go` where the glog call was made. <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This changes ``` I0124 20:53:35.244319 169013 log.go:81] skipping update check I0124 20:53:36.262079 169013 log.go:81] found username for access token ``` to ``` I0129 14:08:42.918230 38925 pulumi.go:231] skipping update check I0129 14:08:45.056866 38925 backend.go:615] found username for access token ``` ## Checklist - [X] I have run `make tidy` to update any new dependencies - [X] I have run `make lint` to verify my code passes the lint check - [X] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works - This is hard to test because it is difficult to reliably intercept stderr from within go tests <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> Co-authored-by: Paul Roberts <proberts@pulumi.com>
2024-01-29 22:51:45 +00:00
glog.ErrorDepthf(1, "%s", FilterString(fmt.Sprintf(format, args...)))
}
func Infof(format string, args ...interface{}) {
Use the Depth variants in glog calls (#15307) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description This allows pulumi's log output to contain the location of where the log call was made from, rather than it always reporting the line in `log.go` where the glog call was made. <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This changes ``` I0124 20:53:35.244319 169013 log.go:81] skipping update check I0124 20:53:36.262079 169013 log.go:81] found username for access token ``` to ``` I0129 14:08:42.918230 38925 pulumi.go:231] skipping update check I0129 14:08:45.056866 38925 backend.go:615] found username for access token ``` ## Checklist - [X] I have run `make tidy` to update any new dependencies - [X] I have run `make lint` to verify my code passes the lint check - [X] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works - This is hard to test because it is difficult to reliably intercept stderr from within go tests <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> Co-authored-by: Paul Roberts <proberts@pulumi.com>
2024-01-29 22:51:45 +00:00
glog.InfoDepthf(1, "%s", FilterString(fmt.Sprintf(format, args...)))
}
func Warningf(format string, args ...interface{}) {
Use the Depth variants in glog calls (#15307) <!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description This allows pulumi's log output to contain the location of where the log call was made from, rather than it always reporting the line in `log.go` where the glog call was made. <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> This changes ``` I0124 20:53:35.244319 169013 log.go:81] skipping update check I0124 20:53:36.262079 169013 log.go:81] found username for access token ``` to ``` I0129 14:08:42.918230 38925 pulumi.go:231] skipping update check I0129 14:08:45.056866 38925 backend.go:615] found username for access token ``` ## Checklist - [X] I have run `make tidy` to update any new dependencies - [X] I have run `make lint` to verify my code passes the lint check - [X] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [ ] I have added tests that prove my fix is effective or that my feature works - This is hard to test because it is difficult to reliably intercept stderr from within go tests <!--- User-facing changes require a CHANGELOG entry. --> - [ ] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @Pulumi employees: If yes, you must submit corresponding changes in the service repo. --> Co-authored-by: Paul Roberts <proberts@pulumi.com>
2024-01-29 22:51:45 +00:00
glog.WarningDepthf(1, "%s", FilterString(fmt.Sprintf(format, args...)))
}
func Flush() {
glog.Flush()
}
func maybeSetFlag(name, value string) {
if f := flag.Lookup(name); f != nil {
err := f.Value.Set(value)
assertNoError(err)
}
}
// InitLogging ensures the logging library has been initialized with the given settings.
func InitLogging(logToStderr bool, verbose int, logFlow bool) {
// Remember the settings in case someone inquires.
LogToStderr = logToStderr
Verbose = verbose
LogFlow = logFlow
// glog uses golang's built in flags package to set configuration values, which is incompatible with how
// we use cobra. In order to accommodate this, we call flag.CommandLine.Parse() with an empty array and
// explicitly set the flags we care about here.
if !flag.Parsed() {
err := flag.CommandLine.Parse([]string{})
assertNoError(err)
}
if logToStderr {
maybeSetFlag("logtostderr", "true")
}
if verbose > 0 {
maybeSetFlag("v", strconv.Itoa(verbose))
}
}
func assertNoError(err error) {
if err != nil {
failfast(err.Error())
}
}
func failfast(msg string) {
panic(fmt.Sprintf("fatal: %v", msg))
}
all: Reformat with gofumpt Per team discussion, switching to gofumpt. [gofumpt][1] is an alternative, stricter alternative to gofmt. It addresses other stylistic concerns that gofmt doesn't yet cover. [1]: https://github.com/mvdan/gofumpt See the full list of [Added rules][2], but it includes: - Dropping empty lines around function bodies - Dropping unnecessary variable grouping when there's only one variable - Ensuring an empty line between multi-line functions - simplification (`-s` in gofmt) is always enabled - Ensuring multi-line function signatures end with `) {` on a separate line. [2]: https://github.com/mvdan/gofumpt#Added-rules gofumpt is stricter, but there's no lock-in. All gofumpt output is valid gofmt output, so if we decide we don't like it, it's easy to switch back without any code changes. gofumpt support is built into the tooling we use for development so this won't change development workflows. - golangci-lint includes a gofumpt check (enabled in this PR) - gopls, the LSP for Go, includes a gofumpt option (see [installation instrutions][3]) [3]: https://github.com/mvdan/gofumpt#installation This change was generated by running: ```bash gofumpt -w $(rg --files -g '*.go' | rg -v testdata | rg -v compilation_error) ``` The following files were manually tweaked afterwards: - pkg/cmd/pulumi/stack_change_secrets_provider.go: one of the lines overflowed and had comments in an inconvenient place - pkg/cmd/pulumi/destroy.go: `var x T = y` where `T` wasn't necessary - pkg/cmd/pulumi/policy_new.go: long line because of error message - pkg/backend/snapshot_test.go: long line trying to assign three variables in the same assignment I have included mention of gofumpt in the CONTRIBUTING.md.
2023-03-03 16:36:39 +00:00
type nopFilter struct{}
func (f *nopFilter) Filter(s string) string {
return s
}
2019-08-14 13:20:56 +00:00
type replacerFilter struct {
replacer *strings.Replacer
}
2019-08-14 13:20:56 +00:00
func (f *replacerFilter) Filter(s string) string {
return f.replacer.Replace(s)
}
func AddGlobalFilter(filter Filter) {
rwLock.Lock()
filters = append(filters, filter)
rwLock.Unlock()
}
func CreateFilter(secrets []string, replacement string) Filter {
items := slice.Prealloc[string](len(secrets))
for _, secret := range secrets {
// For short secrets, don't actually add them to the filter, this is a trade-off we make to prevent
// displaying `[secret]`. Travis does a similar thing, for example.
if len(secret) < 3 {
continue
}
2019-08-14 13:20:56 +00:00
items = append(items, secret, replacement)
// Catch secrets that are serialized to JSON.
bs, err := json.Marshal(secret)
if err != nil {
continue
}
if escaped := string(bs[1 : len(bs)-1]); escaped != secret {
items = append(items, escaped, replacement)
}
}
2019-08-14 13:20:56 +00:00
if len(items) > 0 {
return &replacerFilter{replacer: strings.NewReplacer(items...)}
}
return &nopFilter{}
}
func FilterString(msg string) string {
var localFilters []Filter
rwLock.RLock()
localFilters = filters
rwLock.RUnlock()
for _, filter := range localFilters {
msg = filter.Filter(msg)
}
return msg
}