mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 09:48:32 -05:00
The Go runtime provides a number of configuration knobs that subtly change its behavior, and we cannot control which of these is available over time as we change which version of Go we're building with. It's therefore possible that an OpenTofu user might be intentionally or unintentionally relying on one of these settings for OpenTofu to work on their system, in which case they would be broken if they upgraded to a newer version of OpenTofu which uses a different Go version that no longer supports that setting. These log lines are intended to help us more quickly notice that possibility if someone opens a bug report describing an unexpected behavior change after upgrading to a new OpenTofu minor release series. We can ask the reporter to share "TF_LOG=debug" output from both the previous and new releases to compare, and then these log lines should appear in the older version's output so we can search the Go codebase and issue tracker for each of the mentioned names to learn if the handling of that setting has changed between Go versions. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
68 lines
2.3 KiB
Go
68 lines
2.3 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package main
|
|
|
|
import (
|
|
"log"
|
|
"runtime/metrics"
|
|
"strings"
|
|
|
|
"github.com/opentofu/opentofu/internal/logging"
|
|
"github.com/opentofu/opentofu/version"
|
|
)
|
|
|
|
var Version = version.Version
|
|
|
|
var VersionPrerelease = version.Prerelease
|
|
|
|
// logGodebugUsage produces extra DEBUG log lines if the Go runtime's metrics
|
|
// suggest that code that was run so far relied on any non-default "GODEBUG"
|
|
// settings, which could be helpful in reproducing a bug report if the
|
|
// behavior differs based on such a setting.
|
|
//
|
|
// For this to be useful it must be run just before we're about to exit, after
|
|
// we've already performed all of the requested work.
|
|
func logGodebugUsage() {
|
|
// These constants reflect the documented conventions from the
|
|
// runtime/metrics package, so we can filter for only the metrics that
|
|
// are relevant to this function.
|
|
const godebugMetricPrefix = "/godebug/non-default-behavior/"
|
|
const godebugMetricSuffix = ":events"
|
|
|
|
if !logging.IsDebugOrHigher() {
|
|
// No point in doing any of this work if the log lines are going to
|
|
// be filtered out anyway.
|
|
return
|
|
}
|
|
|
|
metricDescs := metrics.All()
|
|
for _, metric := range metricDescs {
|
|
if !metric.Cumulative || metric.Kind != metrics.KindUint64 {
|
|
// godebug counters are always cumulative uint64, so this quickly
|
|
// filters some irrelevant metrics before we do any string
|
|
// comparisons.
|
|
continue
|
|
}
|
|
if !strings.HasPrefix(metric.Name, godebugMetricPrefix) {
|
|
continue // irrelevant metric
|
|
}
|
|
if !strings.HasSuffix(metric.Name, godebugMetricSuffix) {
|
|
continue // irrelevant metric
|
|
}
|
|
// The metrics API is designed for applications that want to periodically
|
|
// re-extract the same set of metrics in a long-running application by
|
|
// reusing a preallocated buffer, but we don't have that need here and so
|
|
// we'll just read one metric at a time into a single-element array.
|
|
var samples [1]metrics.Sample
|
|
samples[0].Name = metric.Name
|
|
metrics.Read(samples[:])
|
|
if count := samples[0].Value.Uint64(); count != 0 {
|
|
name := metric.Name[len(godebugMetricPrefix) : len(metric.Name)-len(godebugMetricSuffix)]
|
|
log.Printf("[DEBUG] Relied on GODEBUG %q %d times during this execution; behavior might change in future OpenTofu versions", name, count)
|
|
}
|
|
}
|
|
}
|