Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tfsdklog: Introduce outside context level checks for logging functions #149

Merged
merged 1 commit into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/ENHANCEMENTS-20230418-201952.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: ENHANCEMENTS
body: 'tfsdklog: Improved logging performance 20x when logs would be skipped due to
logging level'
time: 2023-04-18T20:19:52.460485-04:00
custom:
Issue: "149"
81 changes: 81 additions & 0 deletions tfsdklog/levels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package tfsdklog

import (
"sync"

"github.com/hashicorp/go-hclog"
)

var (
// rootLevel stores the effective level of the root SDK logger during
// NewRootSDKLogger where the value is deterministically chosen based on
// environment variables, etc. This call generally happens with each new
// provider RPC request. If the environment variable values changed during
// runtime between calls, then inflight provider requests checking this
// value would receive the most up-to-date value which would potentially
// differ with the actual in-context logger level. This tradeoff would only
// effect the inflight requests and should not be an overall performance
// concern in the case of this level causing more context checks until the
// request is over.
rootLevel hclog.Level = hclog.NoLevel

// rootLevelMutex is a read-write mutex that protects rootLevel from
// triggering the data race detector.
rootLevelMutex = sync.RWMutex{}

// subsystemLevels stores the effective level of all subsystem SDK loggers
// during NewSubsystem where the value is deterministically chosen based on
// environment variables, etc. This call generally happens with each new
// provider RPC request. If the environment variable values changed during
// runtime between calls, then inflight provider requests checking this
// value would receive the most up-to-date value which would potentially
// differ with the actual in-context logger level. This tradeoff would only
// effect the inflight requests and should not be an overall performance
// concern in the case of this level causing more context checks until the
// request is over.
subsystemLevels map[string]hclog.Level = make(map[string]hclog.Level)

// subsystemLevelsMutex is a read-write mutex that protects the
// subsystemLevels map from concurrent read and write panics.
subsystemLevelsMutex = sync.RWMutex{}
)

// subsystemWouldLog returns true if the subsystem SDK logger would emit a log
// at the given level. This is performed outside the context-based logger for
// performance.
func subsystemWouldLog(subsystem string, level hclog.Level) bool {
subsystemLevelsMutex.RLock()

setLevel, ok := subsystemLevels[subsystem]

subsystemLevelsMutex.RUnlock()

if !ok {
return false
}

return wouldLog(setLevel, level)
}

// rootWouldLog returns true if the root SDK logger would emit a log at the
// given level. This is performed outside the context-based logger for
// performance.
func rootWouldLog(level hclog.Level) bool {
rootLevelMutex.RLock()

setLevel := rootLevel

rootLevelMutex.RUnlock()

return wouldLog(setLevel, level)
}

// wouldLog returns true if the set level would emit a log at the given
// level. This is performed outside the context-based logger for performance.
func wouldLog(setLevel, checkLevel hclog.Level) bool {
if checkLevel == hclog.Off {
return false
}

return checkLevel >= setLevel
}
Loading
Loading