More visitor log fields

This commit is contained in:
binwiederhier 2023-02-07 16:20:49 -05:00
parent a32e8abc12
commit d44a11325d
5 changed files with 99 additions and 58 deletions

View file

@ -37,7 +37,6 @@ import (
- HIGH Rate limiting: Sensitive endpoints (account/login/change-password/...)
- HIGH Account limit creation triggers when account is taken!
- HIGH Docs
- HIGH make request limit independent of message limit again
- HIGH Self-review
- MEDIUM: Test for expiring messages after reservation removal
- MEDIUM: Test new token endpoints & never-expiring token
@ -138,6 +137,7 @@ const (
// Log tags
const (
tagStartup = "startup"
tagPublish = "publish"
tagFirebase = "firebase"
tagEmail = "email" // Send email
@ -233,7 +233,7 @@ func (s *Server) Run() error {
if s.config.SMTPServerListen != "" {
listenStr += fmt.Sprintf(" %s[smtp]", s.config.SMTPServerListen)
}
log.Info("Listening on%s, ntfy %s, log level is %s", listenStr, s.config.Version, log.CurrentLevel().String())
log.Tag(tagStartup).Info("Listening on%s, ntfy %s, log level is %s", listenStr, s.config.Version, log.CurrentLevel().String())
if log.IsFile() {
fmt.Fprintf(os.Stderr, "Listening on%s, ntfy %s\n", listenStr, s.config.Version)
fmt.Fprintf(os.Stderr, "Logs are written to %s\n", log.File())
@ -347,15 +347,15 @@ func (s *Server) handle(w http.ResponseWriter, r *http.Request) {
if !ok {
httpErr = errHTTPInternalError
}
isNormalError := httpErr.HTTPCode == http.StatusNotFound || httpErr.HTTPCode == http.StatusBadRequest
isNormalError := httpErr.HTTPCode == http.StatusNotFound || httpErr.HTTPCode == http.StatusBadRequest || httpErr.HTTPCode == http.StatusTooManyRequests
if isNormalError {
logvr(v, r).
Err(httpErr).
Debug("Connection closed with HTTP %d (ntfy error %d): %s", httpErr.HTTPCode, httpErr.Code, err.Error())
Debug("Connection closed with HTTP %d (ntfy error %d)", httpErr.HTTPCode, httpErr.Code)
} else {
logvr(v, r).
Err(httpErr).
Info("Connection closed with HTTP %d (ntfy error %d): %s", httpErr.HTTPCode, httpErr.Code, err.Error())
Info("Connection closed with HTTP %d (ntfy error %d)", httpErr.HTTPCode, httpErr.Code)
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", s.config.AccessControlAllowOrigin) // CORS, allow cross-origin requests
@ -1294,21 +1294,21 @@ func (s *Server) execManager() {
staleVisitors := 0
for ip, v := range s.visitors {
if v.Stale() {
log.Trace("Deleting stale visitor %s", v.ip)
log.Tag(tagManager).With(v).Trace("Deleting stale visitor")
delete(s.visitors, ip)
staleVisitors++
}
}
s.mu.Unlock()
log.Debug("Manager: Deleted %d stale visitor(s)", staleVisitors)
log.Tag(tagManager).Field("stale_visitors", staleVisitors).Debug("Deleted %d stale visitor(s)", staleVisitors)
// Delete expired user tokens and users
if s.userManager != nil {
if err := s.userManager.RemoveExpiredTokens(); err != nil {
log.Warn("Error expiring user tokens: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error expiring user tokens")
}
if err := s.userManager.RemoveDeletedUsers(); err != nil {
log.Warn("Error deleting soft-deleted users: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error deleting soft-deleted users")
}
}
@ -1316,47 +1316,47 @@ func (s *Server) execManager() {
if s.fileCache != nil {
ids, err := s.messageCache.AttachmentsExpired()
if err != nil {
log.Warn("Manager: Error retrieving expired attachments: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error retrieving expired attachments")
} else if len(ids) > 0 {
if log.IsDebug() {
log.Debug("Manager: Deleting attachments %s", strings.Join(ids, ", "))
if log.Tag(tagManager).IsDebug() {
log.Tag(tagManager).Debug("Deleting attachments %s", strings.Join(ids, ", "))
}
if err := s.fileCache.Remove(ids...); err != nil {
log.Warn("Manager: Error deleting attachments: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error deleting attachments")
}
if err := s.messageCache.MarkAttachmentsDeleted(ids...); err != nil {
log.Warn("Manager: Error marking attachments deleted: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error marking attachments deleted")
}
} else {
log.Debug("Manager: No expired attachments to delete")
log.Tag(tagManager).Debug("No expired attachments to delete")
}
}
// Prune messages
log.Debug("Manager: Pruning messages")
log.Tag(tagManager).Debug("Manager: Pruning messages")
expiredMessageIDs, err := s.messageCache.MessagesExpired()
if err != nil {
log.Warn("Manager: Error retrieving expired messages: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error retrieving expired messages")
} else if len(expiredMessageIDs) > 0 {
if err := s.fileCache.Remove(expiredMessageIDs...); err != nil {
log.Warn("Manager: Error deleting attachments for expired messages: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error deleting attachments for expired messages")
}
if err := s.messageCache.DeleteMessages(expiredMessageIDs...); err != nil {
log.Warn("Manager: Error marking attachments deleted: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Error marking attachments deleted")
}
} else {
log.Debug("Manager: No expired messages to delete")
log.Tag(tagManager).Debug("No expired messages to delete")
}
// Message count per topic
var messages int
var messagesCached int
messageCounts, err := s.messageCache.MessageCounts()
if err != nil {
log.Warn("Manager: Cannot get message counts: %s", err.Error())
log.Tag(tagManager).Err(err).Warn("Cannot get message counts")
messageCounts = make(map[string]int) // Empty, so we can continue
}
for _, count := range messageCounts {
messages += count
messagesCached += count
}
// Remove subscriptions without subscribers
@ -1364,10 +1364,10 @@ func (s *Server) execManager() {
var subscribers int
for _, t := range s.topics {
subs := t.SubscribersCount()
log.Trace("- topic %s: %d subscribers", t.ID, subs)
log.Tag(tagManager).Trace("- topic %s: %d subscribers", t.ID, subs)
msgs, exists := messageCounts[t.ID]
if subs == 0 && (!exists || msgs == 0) {
log.Trace("Deleting empty topic %s", t.ID)
log.Tag(tagManager).Trace("Deleting empty topic %s", t.ID)
delete(s.topics, t.ID)
continue
}
@ -1389,10 +1389,22 @@ func (s *Server) execManager() {
s.mu.Lock()
messagesCount, topicsCount, visitorsCount := s.messages, len(s.topics), len(s.visitors)
s.mu.Unlock()
log.Info("Stats: %d messages published, %d in cache, %d topic(s) active, %d subscriber(s), %d visitor(s), %d mails received (%d successful, %d failed), %d mails sent (%d successful, %d failed)",
messagesCount, messages, topicsCount, subscribers, visitorsCount,
receivedMailTotal, receivedMailSuccess, receivedMailFailure,
sentMailTotal, sentMailSuccess, sentMailFailure)
log.
Tag(tagManager).
Fields(log.Context{
"messages_published": messagesCount,
"messages_cached": messagesCached,
"topics_active": topicsCount,
"subscribers": subscribers,
"visitors": visitorsCount,
"emails_received": receivedMailTotal,
"emails_received_success": receivedMailSuccess,
"emails_received_failure": receivedMailFailure,
"emails_sent": sentMailTotal,
"emails_sent_success": sentMailSuccess,
"emails_sent_failure": sentMailFailure,
}).
Info("Server stats")
}
func (s *Server) runSMTPServer() error {
@ -1534,7 +1546,7 @@ func (s *Server) limitRequests(next handleFunc) handleFunc {
if util.ContainsIP(s.config.VisitorRequestExemptIPAddrs, v.ip) {
return next(w, r, v)
} else if err := v.RequestAllowed(); err != nil {
logvr(v, r).Err(err).Fields(requestLimiterFields(v.RequestLimiter())).Trace("Request not allowed by rate limiter")
logvr(v, r).Err(err).Trace("Request not allowed by rate limiter")
return errHTTPTooManyRequestsLimitRequests
}
return next(w, r, v)