-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for (internal) debug logging output
OVERVIEW The changes provided by this commit were initially intended to provide a minimal abstraction to support toggling the size of plugin output off/on as needed for troubleshooting. From there the scope widened as further iteration showed that it could be useful to add debug logging support (internally for now) to the library as a whole. To support toggling on/off specific debug log activity, debug log output is currently split into two categories: - debug logging of actions - debug logging of plugin output size The intent of these changes is to provide a way to easily toggle on/off the internal workings of this library. If client code does not enable debug logging, the result should be this library working just as it did before. The current implementation is subject to change as real world testing is applied and feedback collected. CHANGES - allow toggling debug logging output on/off - allow toggling specific debug logging output on/off - e.g., allow all debug messages except for general plugin activity - e.g., allow only debug messages for plugin output size calculations - support setting custom debug logging output target - e.g., redirect debug log messages to a target file instead of stderr (the default debug log target) - add test coverage for new behavior REFERENCES - refs GH-264 - refs GH-271
- Loading branch information
Showing
8 changed files
with
1,375 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
// Copyright 2024 Adam Chalkley | ||
// | ||
// https://github.com/atc0005/go-nagios | ||
// | ||
// Licensed under the MIT License. See LICENSE file in the project root for | ||
// full license information. | ||
|
||
package nagios | ||
|
||
import ( | ||
"io" | ||
"log" | ||
"os" | ||
"strings" | ||
) | ||
|
||
// Logger related values set as constants so that their values are exposed to | ||
// internal tests. | ||
const ( | ||
logMsgPrefix string = "[" + MyPackageName + "] " | ||
logFlags int = log.Ldate | log.Ltime | ||
|
||
// using log.Lshortfile reports the helper function use instead of the | ||
// caller's location. | ||
// | ||
// logFlags int = log.Ldate | log.Ltime | log.Lshortfile | ||
) | ||
|
||
// debugLoggingOptions controls all debug logging behavior for this library. | ||
type debugLoggingOptions struct { | ||
// actions indicates whether actions taken by this library are logged. | ||
// This covers enabling/disabling settings or other general plugin | ||
// activity. | ||
actions bool | ||
|
||
// pluginOutputSize indicates whether all output to the configured plugin | ||
// output sink should be measured and written to the log output sink. | ||
pluginOutputSize bool | ||
} | ||
|
||
// defaultPluginDebugLoggingOutputTarget returns the default debug logging | ||
// output target used when a user-specified value is not provided. | ||
func defaultPluginDebugLoggingOutputTarget() io.Writer { | ||
return os.Stderr | ||
} | ||
|
||
// defaultPluginAbortMessageOutputTarget returns the default abort message | ||
// output target. | ||
func defaultPluginAbortMessageOutputTarget() io.Writer { | ||
return os.Stderr | ||
} | ||
|
||
// defaultPluginDebugLoggerTarget returns the default debug logger target used | ||
// when a user-specified value is not provided for the debug output target. | ||
func defaultPluginDebugLoggerTarget() io.Writer { | ||
// The intended default behavior is to throw away debug log messages if a | ||
// debug log message output target has not been specified. | ||
return io.Discard | ||
} | ||
|
||
// allDebugLoggingOptionsEnabled is a helper function that provides a | ||
// debugLoggingOptions value with all settings enabled. | ||
func allDebugLoggingOptionsEnabled() debugLoggingOptions { | ||
return debugLoggingOptions{ | ||
actions: true, | ||
pluginOutputSize: true, | ||
// Expand this for any new fields added in the future. | ||
} | ||
} | ||
|
||
// allDebugLoggingOptionsDisabled is a helper function that provides a | ||
// debugLoggingOptions value with all settings disabled. | ||
func allDebugLoggingOptionsDisabled() debugLoggingOptions { | ||
return debugLoggingOptions{ | ||
actions: false, | ||
pluginOutputSize: false, | ||
// Expand this for any new fields added in the future. | ||
} | ||
} | ||
|
||
// enableAll enables all debug logging options. The user is able to optionally | ||
// disable select portions of the debug logging output that they do not wish | ||
// to see. | ||
func (dlo *debugLoggingOptions) enableAll() { | ||
*dlo = allDebugLoggingOptionsEnabled() | ||
} | ||
|
||
// disableAll disables all debug logging options. | ||
func (dlo *debugLoggingOptions) disableAll() { | ||
*dlo = allDebugLoggingOptionsDisabled() | ||
} | ||
|
||
// enableActions enables logging plugin actions. | ||
func (dlo *debugLoggingOptions) enableActions() { | ||
dlo.actions = true | ||
} | ||
|
||
// disableActions disables logging plugin actions. | ||
func (dlo *debugLoggingOptions) disableActions() { | ||
dlo.actions = false | ||
} | ||
|
||
// enablePluginOutputSize enables logging plugin output size. | ||
func (dlo *debugLoggingOptions) enablePluginOutputSize() { | ||
dlo.pluginOutputSize = true | ||
} | ||
|
||
// disablePluginOutputSize disables logging plugin output size. | ||
func (dlo *debugLoggingOptions) disablePluginOutputSize() { | ||
dlo.pluginOutputSize = false | ||
} | ||
|
||
// DebugLoggingEnableAll changes the default state of all debug logging | ||
// options for this library from disabled to enabled. | ||
// | ||
// Once enabled, debug logging output is emitted to os.Stderr. This can be | ||
// overridden by explicitly setting a custom debug output target. | ||
func (p *Plugin) DebugLoggingEnableAll() { | ||
// Enable all (granular) debug log options. | ||
p.debugLogging.enableAll() | ||
|
||
// Ensure we have a valid output target, but do not overwrite any custom | ||
// target already set. | ||
if p.logOutputSink == nil { | ||
p.setFallbackDebugLogTarget() | ||
} | ||
|
||
// Connect logger to configured debug log target. | ||
p.setupLogger() | ||
} | ||
|
||
// DebugLoggingDisableAll changes the default state of all debug logging | ||
// options for this library from any custom state back to the default state of | ||
// disabled. | ||
// | ||
// Any custom debug log output target remains as it was before calling this | ||
// function. | ||
func (p *Plugin) DebugLoggingDisableAll() { | ||
p.debugLogging.disableAll() | ||
} | ||
|
||
// DebugLoggingDisableActions disables debug logging of general "actions" or | ||
// plugin activity. This is the most verbose debug logging output generated by | ||
// this library. | ||
func (p *Plugin) DebugLoggingDisableActions() { | ||
p.debugLogging.disableActions() | ||
} | ||
|
||
// DebugLoggingEnableActions enables debug logging of general "actions" or | ||
// plugin activity. This is the most verbose debug logging output generated by | ||
// this library. | ||
// | ||
// Once enabled, debug logging output is emitted to os.Stderr. This can be | ||
// overridden by explicitly setting a custom debug output target. | ||
func (p *Plugin) DebugLoggingEnableActions() { | ||
p.debugLogging.enableActions() | ||
|
||
// Ensure we have a valid output target, but do not overwrite any custom | ||
// target already set. | ||
if p.logOutputSink == nil { | ||
p.setFallbackDebugLogTarget() | ||
} | ||
|
||
// Connect logger to configured debug log target. | ||
p.setupLogger() | ||
} | ||
|
||
// DebugLoggingDisablePluginOutputSize disables debug logging of plugin output | ||
// size calculations. | ||
func (p *Plugin) DebugLoggingDisablePluginOutputSize() { | ||
p.debugLogging.disablePluginOutputSize() | ||
} | ||
|
||
// DebugLoggingEnablePluginOutputSize enables debug logging of plugin output | ||
// size calculations. This debug logging output produces minimal output. | ||
// | ||
// Once enabled, debug logging output is emitted to os.Stderr. This can be | ||
// overridden by explicitly setting a custom debug output target. | ||
func (p *Plugin) DebugLoggingEnablePluginOutputSize() { | ||
p.debugLogging.enablePluginOutputSize() | ||
|
||
// Ensure we have a valid output target, but do not overwrite any custom | ||
// target already set. | ||
if p.logOutputSink == nil { | ||
p.setFallbackDebugLogTarget() | ||
} | ||
|
||
// Connect logger to configured debug log target. | ||
p.setupLogger() | ||
} | ||
|
||
// SetDebugLoggingOutputTarget overrides the current debug logging target with | ||
// the given output target. If the given output target is not valid the | ||
// current target will be used instead. If there isn't a debug logging target | ||
// already set then the default debug logging output target of os.Stderr will | ||
// be used. This behavior is chosen for consistency with the current behavior | ||
// of the Plugin.SetOutputTarget function. | ||
// | ||
// NOTE: While an error message is logged when calling this function with an | ||
// invalid target, calling this function does not change the default debug | ||
// logging state from disabled to enabled. That step must be performed | ||
// separately by either enabling all debug logging options OR enabling select | ||
// debug logging options. | ||
func (p *Plugin) SetDebugLoggingOutputTarget(w io.Writer) { | ||
if w == nil { | ||
if p.logOutputSink == nil { | ||
p.setFallbackDebugLogTarget() | ||
} | ||
|
||
// Connect logger to configured debug log target. | ||
p.setupLogger() | ||
|
||
// We log using an "unfiltered" logger call to ensure this has the | ||
// best chance of being seen. | ||
p.log("invalid output target provided; using default debug log target instead") | ||
|
||
return | ||
} | ||
|
||
p.logOutputSink = w | ||
|
||
// Connect logger to configured debug log target. | ||
p.setupLogger() | ||
|
||
// Use a filtered logger call to allow this message to be emitted or | ||
// excluded based on user-specified debug logging settings. | ||
p.logAction("custom debug logging target set as requested") | ||
} | ||
|
||
// DebugLoggingOutputTarget returns the user-specified debug output target or | ||
// the default value if one was not specified. | ||
func (p *Plugin) DebugLoggingOutputTarget() io.Writer { | ||
if p.logOutputSink == nil { | ||
return defaultPluginDebugLoggingOutputTarget() | ||
} | ||
|
||
return p.logOutputSink | ||
} | ||
|
||
func (p *Plugin) setFallbackDebugLogTarget() { | ||
p.logOutputSink = defaultPluginDebugLoggingOutputTarget() | ||
} | ||
|
||
// setupLogger should be called after the debug log output sink is explicitly | ||
// configured. If called before configuring the debug log output sink the | ||
// plugin's default debug logger target will be used instead. | ||
func (p *Plugin) setupLogger() { | ||
var loggerTarget io.Writer | ||
switch { | ||
case p.logOutputSink == nil: | ||
loggerTarget = defaultPluginDebugLoggerTarget() | ||
default: | ||
loggerTarget = p.logOutputSink | ||
} | ||
|
||
p.logger = log.New(loggerTarget, logMsgPrefix, logFlags) | ||
} | ||
|
||
// log uses the plugin's logger to write the given message to the configured | ||
// output sink. | ||
func (p *Plugin) log(msg string) { | ||
if p.logger == nil { | ||
return | ||
} | ||
|
||
if !strings.HasSuffix(msg, CheckOutputEOL) { | ||
msg += CheckOutputEOL | ||
} | ||
|
||
p.logger.Print(msg) | ||
} | ||
|
||
// logAction is used to log actions taken by this library such as | ||
// enabling/disabling settings or other general plugin activity. | ||
func (p *Plugin) logAction(msg string) { | ||
if !p.debugLogging.actions { | ||
return | ||
} | ||
|
||
p.log(msg) | ||
} | ||
|
||
// logPluginOutputSize is used to log activity related to measuring all output | ||
// to the configured plugin output sink. | ||
func (p *Plugin) logPluginOutputSize(msg string) { | ||
if !p.debugLogging.pluginOutputSize { | ||
return | ||
} | ||
|
||
p.log(msg) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Copyright 2024 Adam Chalkley | ||
// | ||
// https://github.com/atc0005/go-nagios | ||
// | ||
// Licensed under the MIT License. See LICENSE file in the project root for | ||
// full license information. | ||
|
||
// Package nagios_test provides test coverage for exported package | ||
// functionality. | ||
// | ||
//nolint:dupl,gocognit // ignore "lines are duplicate of" and function complexity | ||
package nagios_test |
Oops, something went wrong.