* improved debugging/logging support

- add mu4e-toggle-logging to enable/disable logging
  - add mu4e-show-log to view the log buffer, and bind it to '$' in the
    main/header/view buffers
  - add a note about it to the doc (mu4e.texi)
  - make mu4e-log the the new logging function, use colors to distinguish
    incoming/outgoing data
  - only keep last 1200 lines of log in the log buffer
This commit is contained in:
djcb 2012-04-16 18:31:48 +03:00
parent 0be852b288
commit bc13c49736
7 changed files with 95 additions and 17 deletions

View File

@ -287,6 +287,7 @@ after the end of the search results."
(define-key map (kbd "RET") 'mu4e-view-message) (define-key map (kbd "RET") 'mu4e-view-message)
(define-key map [mouse-2] 'mu4e-view-message) (define-key map [mouse-2] 'mu4e-view-message)
(define-key map "$" 'mu4e-show-log)
(define-key map "H" 'mu4e-display-manual) (define-key map "H" 'mu4e-display-manual)
;; menu ;; menu

View File

@ -44,6 +44,7 @@
(define-key map "f" 'smtpmail-send-queued-mail) (define-key map "f" 'smtpmail-send-queued-mail)
(define-key map "U" 'mu4e-update-mail-show-window) (define-key map "U" 'mu4e-update-mail-show-window)
(define-key map "$" 'mu4e-show-log)
(define-key map "H" 'mu4e-display-manual) (define-key map "H" 'mu4e-display-manual)
map) map)

View File

@ -1,4 +1,4 @@
;;; mu4e-proc.el -- part of mu4e, the mu mail user agent ;; mu4e-proc.el -- part of mu4e, the mu mail user agent
;; ;;
;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema ;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema
@ -162,11 +162,11 @@ updated as well, with all processed sexp data removed."
6. a compose looks like: 6. a compose looks like:
(:compose <reply|forward|edit|new> [:original<msg-sexp>] [:include <attach>]) (:compose <reply|forward|edit|new> [:original<msg-sexp>] [:include <attach>])
`mu4e-compose-func'." `mu4e-compose-func'."
(mu4e-proc-log "* Received %d byte(s)" (length str)) (mu4e-log 'misc "* Received %d byte(s)" (length str))
(setq mu4e-buf (concat mu4e-buf str)) ;; update our buffer (setq mu4e-buf (concat mu4e-buf str)) ;; update our buffer
(let ((sexp (mu4e-proc-eat-sexp-from-buf))) (let ((sexp (mu4e-proc-eat-sexp-from-buf)))
(while sexp (while sexp
(mu4e-proc-log "<- %S" sexp) (mu4e-log 'from-server "%S" sexp)
(cond (cond
;; a header plist can be recognized by the existence of a :date field ;; a header plist can be recognized by the existence of a :date field
((plist-get sexp :date) ((plist-get sexp :date)
@ -260,24 +260,12 @@ terminates."
(t (t
(message "Something bad happened to the mu server process"))))) (message "Something bad happened to the mu server process")))))
(defconst mu4e-proc-log-buffer-name "*mu4e-log*"
"*internal* Name of the logging buffer.")
(defun mu4e-proc-log (frm &rest args)
"Write something in the *mu4e-log* buffer - mainly useful for debugging."
(when mu4e-debug
(with-current-buffer (get-buffer-create mu4e-proc-log-buffer-name)
(goto-char (point-max))
(insert (apply 'format (concat (format-time-string "%Y-%m-%d %T "
(current-time)) frm "\n") args)))))
(defun mu4e-proc-send-command (frm &rest args) (defun mu4e-proc-send-command (frm &rest args)
"Send as command to the mu server process; start the process if needed." "Send as command to the mu server process; start the process if needed."
(unless (mu4e-proc-is-running) (unless (mu4e-proc-is-running)
(mu4e-start-proc)) (mu4e-start-proc))
(let ((cmd (apply 'format frm args))) (let ((cmd (apply 'format frm args)))
(mu4e-proc-log (concat "-> " cmd)) (mu4e-log 'to-server "%s" cmd)
(process-send-string mu4e-mu-proc (concat cmd "\n")))) (process-send-string mu4e-mu-proc (concat cmd "\n"))))

View File

@ -472,5 +472,63 @@ server has the expected values."
(mu4e-kill-proc) (mu4e-kill-proc)
(kill-buffer))) (kill-buffer)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; logging / debugging
(defun mu4e-log (type frm &rest args)
"Write a message of TYPE with format-string FRM and ARGS in
*mu4e-log* buffer, if the variable mu4e-debug is non-nil. Type is
either 'to-server, 'from-server or 'misc. This function is meant for debugging."
(when mu4e-debug
(with-current-buffer (get-buffer-create mu4e-log-buffer-name)
(view-mode)
(setq buffer-undo-list t)
(let* ((inhibit-read-only t)
(tstamp (propertize (format-time-string "%Y-%m-%d %T" (current-time))
'face 'font-lock-string-face))
(msg-face
(case type
(from-server 'font-lock-type-face)
(to-server 'font-lock-function-name-face)
(misc 'font-lock-variable-name-face)
(otherwise (error "Unsupported log type"))))
(msg (propertize (apply 'format frm args) 'face msg-face)))
(goto-char (point-max))
(insert tstamp
(case type
(from-server " <- ")
(to-server " -> " )
(otherwise " "))
msg "\n")
;; if `mu4e-log-max-lines is specified and exceeded, clearest the oldest
;; lines
(when (numberp mu4e-log-max-lines)
(let ((lines (count-lines (point-min) (point-max))))
(when (> lines mu4e-log-max-lines)
(goto-char (point-max))
(forward-line (- mu4e-log-max-lines lines))
(beginning-of-line)
(delete-region (point-min) (point)))))))))
(defun mu4e-toggle-logging ()
"Toggle between enabling/disabling debug-mode (in debug-mode,
mu4e logs some of its internal workings to a log-buffer. See
`mu4e-visit-log'."
(interactive)
(setq mu4e-debug (not mu4e-debug))
(message "mu4e debug logging has been %s"
(if mu4e-debug "enabled" "disabled")))
(defun mu4e-show-log ()
"Visit the mu4e debug log."
(interactive)
(let ((buf (get-buffer mu4e-log-buffer-name)))
(unless (buffer-live-p buf)
(error "No debug log available"))
(switch-to-buffer buf)))
(provide 'mu4e-utils) (provide 'mu4e-utils)
;;; End of mu4e-utils.el ;;; End of mu4e-utils.el

View File

@ -465,6 +465,14 @@ in which case it will be equal to `:to'.)")
(defvar mu4e-captured-message nil (defvar mu4e-captured-message nil
"*internal* the last-captured message (the s-expression).") "*internal* the last-captured message (the s-expression).")
(defvar mu4e-log-max-lines 1200
"*internal* Last <n> number of lines to keep around in the buffer.")
(defconst mu4e-log-buffer-name "*mu4e-log*"
"*internal* Name of the logging buffer.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; our handlers funcs ;; our handlers funcs

View File

@ -288,6 +288,7 @@ is nil, and otherwise open it."
(define-key map "U" 'mu4e-view-unmark-all) (define-key map "U" 'mu4e-view-unmark-all)
(define-key map "x" 'mu4e-view-marked-execute) (define-key map "x" 'mu4e-view-marked-execute)
(define-key map "$" 'mu4e-show-log)
(define-key map "H" 'mu4e-display-manual) (define-key map "H" 'mu4e-display-manual)
;; menu ;; menu
@ -359,6 +360,8 @@ is nil, and otherwise open it."
(make-local-variable 'mu4e-lines-wrapped) (make-local-variable 'mu4e-lines-wrapped)
(make-local-variable 'mu4e-cited-hidden) (make-local-variable 'mu4e-cited-hidden)
(setq buffer-undo-list t) ;; don't record undo info
;; filladapt is much better than the built-in filling ;; filladapt is much better than the built-in filling
;; esp. with '>' cited parts ;; esp. with '>' cited parts
(when (fboundp 'filladapt-mode) (when (fboundp 'filladapt-mode)

View File

@ -43,6 +43,7 @@ describes how to set up and use @t{mu4e}.
Appendices Appendices
* How it works:: Some notes about the implementation of mu4e * How it works:: Some notes about the implementation of mu4e
* Logging and debugging:: How to debug problems in @t{mu4e}
* GNU Free Documentation License:: The license of this manual. * GNU Free Documentation License:: The license of this manual.
@end menu @end menu
@ -1395,10 +1396,10 @@ menu assumes the default key-bindings, as do the clicks-on-bookmarks.
@item @emph{Attachments are not accessible in draft/sent messages}. Currently, @item @emph{Attachments are not accessible in draft/sent messages}. Currently,
attachments in saved messages are special strings, which are transformed into attachments in saved messages are special strings, which are transformed into
the actual attachments when sending. However, you cannot access them afterwards. the actual attachments when sending. However, you cannot access them afterwards.
@end itemize @end itemize
@node How it works @node How it works
@appendix How it works @appendix How it works
@ -1549,6 +1550,24 @@ we registered will be called, and it check the version we got from the
@t{pong} with the version we expected, and raises an error, if they differ. @t{pong} with the version we expected, and raises an error, if they differ.
@node Logging and debugging
@appendix Logging and debugging
As explained in @ref{How it works}, @t{mu4e} communicates with its backend
(@t{mu server}) by sending commands and receiving responses (s-expressions).
For debugging purposes, it can be very useful to see this data. For this
reason, @t{mu4e} can log all these messages. Note that the 'protocol' is
documented to some extent in the @t{mu-server} manpage.
You can enable (and disable) logging with @t{M-x mu4e-toggle-logging}. The
log-buffer is called @t{*mu4e-log-buffer*}, and in the @ref{Main view},
@ref{Headers view} and @t{Message view}, there's a keybinding @key{$} that
will take you there. You can quit it by pressing @key{q}.
Note that logging can be a bit resource-intensive, so you may not want to
leave it on all the time. By default, the log only maintains the most recent
1200 lines.
@node GNU Free Documentation License @node GNU Free Documentation License
@appendix GNU Free Documentation License @appendix GNU Free Documentation License