github.com/haraldrudell/parl@v0.4.176/log.go (about)

     1  /*
     2  © 2020–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package parl
     7  
     8  import (
     9  	"os"
    10  
    11  	"github.com/haraldrudell/parl/plog"
    12  )
    13  
    14  const (
    15  	// extra stack frame for the parl indirection, used by 6 functions:
    16  	// Debug() GetDebug() D() GetD() IsThisDebug() IsThisDebugN()
    17  	logStackFramesToSkip = 1
    18  )
    19  
    20  // stderrLogger prints to standard error with proper code location
    21  var stderrLogger = plog.NewLogFrames(nil, logStackFramesToSkip)
    22  
    23  // stderrLogger prints to standard out with proper code location
    24  var stdoutLogger = plog.NewLogFrames(os.Stdout, logStackFramesToSkip)
    25  
    26  // Out always prints to standard out
    27  //   - if debug is enabled, code location is appended
    28  func Out(format string, a ...interface{}) {
    29  	stdoutLogger.Log(format, a...)
    30  }
    31  
    32  // Outw always prints to standard out without ensuring terminating newline
    33  func Outw(format string, a ...interface{}) {
    34  	stderrLogger.Logw(format, a...)
    35  }
    36  
    37  // Log always prints to standard error
    38  //   - if debug is enabled, code location is appended
    39  func Log(format string, a ...interface{}) {
    40  	stderrLogger.Log(format, a...)
    41  }
    42  
    43  // Logw always prints to standard error
    44  //   - Logw outputs without ensruing ending newline
    45  func Logw(format string, a ...interface{}) {
    46  	stderrLogger.Logw(format, a...)
    47  }
    48  
    49  // Console always prints to interactive standard out
    50  //   - intended for command-line interactivity.
    51  //   - if debug is enabled, code location is appended.
    52  func Console(format string, a ...interface{}) {
    53  	stderrLogger.Log(format, a...)
    54  }
    55  
    56  // Consolew always prints to standard out
    57  //   - intended for command-line interactivity.
    58  //   - Consolew does not ensure ending newline
    59  func Consolew(format string, a ...interface{}) {
    60  	stderrLogger.Logw(format, a...)
    61  }
    62  
    63  // Info prints unless silence has been configured with SetSilence(true)
    64  //   - Info outputs to standard error
    65  //   - IsSilent() deteremines the state of silence
    66  //   - if debug is enabled, code location is appended
    67  func Info(format string, a ...interface{}) {
    68  	stderrLogger.Info(format, a...)
    69  }
    70  
    71  // Debug outputs only if debug is configured globally or for the executing function
    72  //   - Debug outputs to standard error
    73  //   - code location is appended
    74  func Debug(format string, a ...interface{}) {
    75  	stderrLogger.Debug(format, a...)
    76  }
    77  
    78  // GetDebug returns a function value that can be used to invokes logging
    79  //   - output to stderr if debug is enabled for the specified caller frame
    80  //   - the caller frame is appended
    81  //   - the function value can be passed around or invoked later
    82  func GetDebug(skipFrames int) (debug func(format string, a ...interface{})) {
    83  	return stderrLogger.GetDebug(skipFrames)
    84  }
    85  
    86  // GetD returns a function value that always invokes logging
    87  //   - output to stderr
    88  //   - the caller frame is appended
    89  //   - D is meant for temporary output intended to be removed
    90  //     prior to check-in
    91  //   - the function value can be passed around or invoked later
    92  func GetD(skipFrames int) (debug func(format string, a ...interface{})) {
    93  	return stderrLogger.GetD(skipFrames)
    94  }
    95  
    96  // IsThisDebug returns whether the executing code location
    97  // has debug logging enabled
    98  //   - true when -debug globally enabled using SetDebug(true)
    99  //   - true when the -verbose regexp set with SetRegexp matches
   100  //   - matched against [pruntime.CodeLocation.FuncName]
   101  //   - “github.com/haraldrudell/parl/mains.(*Executable).AddErr”
   102  func IsThisDebug() bool {
   103  	return stderrLogger.IsThisDebug()
   104  }
   105  
   106  // IsThisDebugN returns whether the specified stack frame
   107  // has debug logging enabled. 0 means caller of IsThisDebugN.
   108  //   - true when -debug globally enabled using SetDebug(true)
   109  //   - true when the -verbose regexp set with SetRegexp matches
   110  func IsThisDebugN(skipFrames int) (isDebug bool) {
   111  	return stderrLogger.IsThisDebugN(skipFrames)
   112  }
   113  
   114  // IsSilent if true it means that Info does not print
   115  func IsSilent() (isSilent bool) {
   116  	return stderrLogger.IsSilent()
   117  }
   118  
   119  // SetRegexp defines a regular expression for function-level debug
   120  // printing to stderr.
   121  //   - SetRegexp affects Debug() GetDebug() IsThisDebug() IsThisDebugN()
   122  //     functions.
   123  //
   124  // # Regular Expression
   125  //
   126  // Regular expression is the RE2 [syntax] used by golang.
   127  // command-line documentation: “go doc regexp/syntax”.
   128  // The regular expression is matched against code location.
   129  //
   130  // # Code Location Format
   131  //
   132  // Code location is the fully qualified function name
   133  // for the executing code line being evaluated.
   134  // This is a fully qualified golang package path, ".",
   135  // a possible type name in parenthesis ending with "." and the function name.
   136  //
   137  //   - method with pointer receiver:
   138  //   - — "github.com/haraldrudell/parl/mains.(*Executable).AddErr"
   139  //   - — sample regexp: mains...Executable..AddErr
   140  //   - top-level function:
   141  //   - — "github.com/haraldrudell/parl/g0.NewGoGroup"
   142  //   - — sample regexp: g0.NewGoGroup
   143  //
   144  // To obtain the fully qualified function name for a particular location:
   145  //
   146  //	parl.Log(pruntime.NewCodeLocation(0).String())
   147  //
   148  // [syntax]: https://github.com/google/re2/wiki/Syntax
   149  func SetRegexp(regExp string) (err error) {
   150  	return stderrLogger.SetRegexp(regExp)
   151  }
   152  
   153  // SetSilent(true) prevents Info() invocations from printing
   154  func SetSilent(silent bool) {
   155  	stderrLogger.SetSilent(silent)
   156  }
   157  
   158  // if SetDebug is true, Debug prints everywhere produce output
   159  //   - other printouts have location appended
   160  //   - More selective debug printing can be achieved using SetInfoRegexp
   161  //     that matches on function names.
   162  func SetDebug(debug bool) {
   163  	stderrLogger.SetDebug(debug)
   164  }
   165  
   166  // D always prints to stderr with code location. Thread-safe
   167  //   - D is meant for temporary output intended to be removed
   168  //     prior to check-in
   169  func D(format string, a ...interface{}) {
   170  	stderrLogger.D(format, a...)
   171  }