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

Add support for (internal) debug logging output #274

Merged
merged 1 commit into from
Oct 24, 2024
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 exported_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,12 @@ func TestExtractAndDecodeASCII85Payload_FailsToExtractAndDecodePayloadWithInvali
this value is what we're left with:
\x90\xac8 \x04\x9f\xe6\xc2\xfe\x87\x91\x1a\xa6\x85'\xce2
Reproduce via:
fmt.Printf("%+q\n", decodedPayload)
See also:
https://go.dev/blog/strings
This in no way represents the encoded payload nor the original
extracted & decoded payload we would expect to see.
*/
Expand Down
291 changes: 291 additions & 0 deletions logging.go
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)
}
12 changes: 12 additions & 0 deletions logging_exported_test.go
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
Loading
Loading