diff --git a/README.md b/README.md index 081cb96..da00522 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,22 @@ log.D.Fmt("the level is %s", "debug") log.T.Fmt("the level is %s", "trace") ``` +### Exclude timestamp + +When running under systemd it is nice to not include the redundant timestamp +directly from the logging package (since journald will already insert one). To +exclude the timestamp simply set the `ULOG_NOTIMESTAMP` environment variable +to `true`. + +e.g. in a systemd unit file + +``` +[Service] +# ... +Environment="ULOG_NOTIMESTAMP=true" +``` + + ### License The `cattlecloud.net/go/ulog` module is open source under the [BSD-3-Clause](LICENSE) license. diff --git a/ulog.go b/ulog.go index d414c96..c816d21 100644 --- a/ulog.go +++ b/ulog.go @@ -6,6 +6,7 @@ package ulog import ( "fmt" + "os" "strconv" "time" ) @@ -21,6 +22,7 @@ const ( type Log struct { name string level int + short bool E Output // error logs W Output // warn logs @@ -33,14 +35,18 @@ type Output interface { Fmt(string, ...any) } -type standard struct { +type format struct { prefix string name string + short bool } -func (s *standard) Fmt(msg string, args ...any) { - now := time.Now().Format("01/02 15:04:05") - complete := now + " " + s.prefix + " [" + s.name + "] " + fmt.Sprintf(msg, args...) +func (s *format) Fmt(msg string, args ...any) { + complete := s.prefix + " [" + s.name + "] " + fmt.Sprintf(msg, args...) + if !s.short { + now := time.Now().Format("01/02 15:04:05") + complete = now + " " + complete + } fmt.Println(complete) } @@ -50,7 +56,11 @@ func (null) Fmt(string, ...any) { // do nothing } -func output(name string, minimum, level int) Output { +func output(name string, short bool, minimum, level int) Output { + if level > minimum { + return null{} + } + var prefix string switch level { case Error: @@ -65,31 +75,35 @@ func output(name string, minimum, level int) Output { prefix = "TRACE" } - if level <= minimum { - return &standard{ - prefix: prefix, - name: name, - } + return &format{ + prefix: prefix, + name: name, + short: shorten(short), } +} - return null{} +func shorten(force bool) bool { + env := os.Getenv("ULOG_NOTIMESTAMP") + v, _ := strconv.ParseBool(env) + return v || force } func New(name string, opts ...Option) *Log { log := &Log{ name: name, level: Debug, + short: false, } for _, opt := range opts { opt(log) } - log.E = output(name, log.level, Error) - log.W = output(name, log.level, Warn) - log.I = output(name, log.level, Info) - log.D = output(name, log.level, Debug) - log.T = output(name, log.level, Trace) + log.E = output(name, log.short, log.level, Error) + log.W = output(name, log.short, log.level, Warn) + log.I = output(name, log.short, log.level, Info) + log.D = output(name, log.short, log.level, Debug) + log.T = output(name, log.short, log.level, Trace) return log } @@ -109,3 +123,7 @@ func SetLevel(value int) Option { } return func(l *Log) { l.level = value } } + +func SetNoTimestamp() Option { + return func(l *Log) { l.short = true } +} diff --git a/ulog_test.go b/ulog_test.go index ea189f6..f92ba85 100644 --- a/ulog_test.go +++ b/ulog_test.go @@ -69,3 +69,12 @@ func Test_SetLevel(t *testing.T) { t.Log("complete") } + +func Test_SetNoTimestamp(t *testing.T) { + t.Parallel() + + t.Run("shorten", func(_ *testing.T) { + log := New("test-timestamp", SetNoTimestamp()) + log.I.Fmt("no timestamp here") + }) +}