diff --git a/log/event.go b/log/event.go index 775159b5..ccde4126 100644 --- a/log/event.go +++ b/log/event.go @@ -3,6 +3,7 @@ package log import ( "encoding/json" "fmt" + "heckel.io/ntfy/util" "log" "os" "sort" @@ -11,12 +12,11 @@ import ( ) const ( - fieldTag = "tag" - fieldError = "error" - fieldTimeTaken = "time_taken_ms" - fieldExitCode = "exit_code" - tagStdLog = "stdlog" - timestampFormat = "2006-01-02T15:04:05.999Z07:00" + fieldTag = "tag" + fieldError = "error" + fieldTimeTaken = "time_taken_ms" + fieldExitCode = "exit_code" + tagStdLog = "stdlog" ) // Event represents a single log event @@ -143,7 +143,7 @@ func (e *Event) Render(l Level, message string, v ...any) string { } e.Message = fmt.Sprintf(message, v...) e.Level = l - e.Timestamp = e.time.Format(timestampFormat) + e.Timestamp = util.FormatTime(e.time) if !appliedContexters { e.applyContexters() } diff --git a/server/visitor.go b/server/visitor.go index 80bac46f..63a3ac60 100644 --- a/server/visitor.go +++ b/server/visitor.go @@ -143,6 +143,7 @@ func (v *visitor) contextNoLock() log.Context { fields := log.Context{ "visitor_id": visitorID(v.ip, v.user), "visitor_ip": v.ip.String(), + "visitor_seen": util.FormatTime(v.seen), "visitor_messages": info.Stats.Messages, "visitor_messages_limit": info.Limits.MessageLimit, "visitor_messages_remaining": info.Stats.MessagesRemaining, diff --git a/util/time.go b/util/time.go index 1a455770..14aa3936 100644 --- a/util/time.go +++ b/util/time.go @@ -14,6 +14,15 @@ var ( durationStrRegex = regexp.MustCompile(`(?i)^(\d+)\s*(d|days?|h|hours?|m|mins?|minutes?|s|secs?|seconds?)$`) ) +const ( + timestampFormat = "2006-01-02T15:04:05.999Z07:00" // Like RFC3339, but with milliseconds +) + +// FormatTime formats a time.Time in a RFC339-like format that includes milliseconds +func FormatTime(t time.Time) string { + return t.Format(timestampFormat) +} + // NextOccurrenceUTC takes a time of day (e.g. 9:00am), and returns the next occurrence // of that time from the current time (in UTC). func NextOccurrenceUTC(timeOfDay, base time.Time) time.Time {