   (toggle-truncate-lines 1)
   (setq font-lock-defaults ovirt-log-analyzer-font-lock-keywords)
   (setq buffer-invisibility-spec '(yes))
+  (add-hook 'before-save-hook 'ovirt-log-analyzer-cleanup nil t)
   (ovirt-log-analyzer-process))
 
 (provide 'ovirt-log-analyzer)

              (when visible-tags
                (goto-char tag-beg)
                (while (re-search-forward "\\(Host\\|VM\\)=\\([^; |]*\\)" tag-end t)
                  (let ((entity (match-string 1))
                        (value (match-string 2))
                        (o (make-overlay (match-beginning 0) (match-end 0))))
                    (overlay-put o 'invisible 'no)
                    (overlay-put o 'face 'font-lock-variable-name-face)
                    (overlay-put o 'before-string " ")
                    (overlay-put o 'priority 10)
                    (cond
                     ((string= entity "Host")
                      (overlay-put o 'ovirt-log-analyzer-host value))
                     ((string= entity "VM")
                      (overlay-put o 'ovirt-log-analyzer-vm value)))
                    (goto-char (overlay-end o)))))
              (overlay-put tag-overlay 'invisible 'yes))
          (let ((o (make-overlay (line-beginning-position) (1+ (line-end-position)))))
            (overlay-put o 'invisible 'yes)))
        (forward-line))
      (when (> max-file-field-length 0)
        (goto-char (point-min))
        (let (point)
          (ovirt-log-analyzer-while 100 (and (not (eobp))
                                            (setq point (next-single-char-property-change (point) 'ovirt-log-analyzer-file-field-length)))
            (goto-char point)
            (let ((length (get-char-property (point) 'ovirt-log-analyzer-file-field-length)))
              (when (and length (< length max-file-field-length))
                (let ((overlay (cl-find-if #'(lambda (o) (overlay-get o 'ovirt-log-analyzer-file-field-length)) (overlays-at (point)))))
                  (overlay-put overlay 'after-string (make-string (- max-file-field-length length) ? )))))
            (goto-char (1+ (point))))))
      (when unknown-tags
        (message "Unknown tags found: %s" (mapconcat #'identity unknown-tags "; "))))))


  (dolist (o (overlays-in (point-min) (point-max)))
    (when (overlay-get o 'ovirt-log-analyzer-filter)
      (let ((invisible (not (eq (overlay-get o 'invisible) 'yes))))
        (overlay-put o 'invisible (if invisible 'yes nil))
        (overlay-put o 'priority (if invisible 20 0))))))

(defun ovirt-log-analyzer-add-text (point string &optional face)
  (save-excursion
    (goto-char point)
    (insert (propertize string 'face face 'ovirt-log-analyzer-virtual t))))

(defun ovirt-log-analyzer-cleanup ()
  (let ((inhibit-read-only t))
    (remove-overlays)
    (remove-list-of-text-properties (point-min) (point-max)
                                    '(ovirt-log-analyzer-file
                                      ovirt-log-analyzer-file-field-length
                                      ovirt-log-analyzer-file-reference
                                      ovirt-log-analyzer-host
                                      ovirt-log-analyzer-vm
                                      after-string
                                      face
                                      help-echo
                                      invisible))
    (let ((point (point-min)))
      (while (< point (point-max))
        (let ((beg (next-single-property-change point 'ovirt-log-analyzer-virtual)))
          (if beg
              (let ((end (or (next-single-property-change beg 'ovirt-log-analyzer-virtual) (eobp))))
                (delete-region beg end)
                (setq point beg))
            (setq point (point-max))))))))

(defun ovirt-log-analyzer-process ()
  (save-excursion
    (goto-char (point-min))
    (let ((inhibit-read-only t)
          (modified-p (buffer-modified-p))
          (unknown-tags '())
          (max-file-field-length 0))
      (ovirt-log-analyzer-cleanup)
      (ovirt-log-analyzer-while 500 (not (eobp))
        (if (looking-at "[0-9][^|\n]*| \\( *[^|\n]+:[0-9]+\\) *| \\( *\\([^|\n]*\\) |\\).*$")
            (let* ((beg (match-beginning 0))
                   (end (match-end 0))
                   (file-point (match-beginning 1))
                   (tag-beg (match-beginning 2))
                   (tag-end (match-end 2))
                   (file-field (match-string 1))
                   (tag-field (match-string 3))
                   (tag-list (split-string (match-string 3) ";"))
                   (visible-tags nil))
              (add-text-properties beg end (list 'help-echo (mapconcat #'identity tag-list "; ")
                                                 'ovirt-log-analyzer-file-reference file-field
                                                 'ovirt-log-analyzer-file (car (split-string file-field ":"))))
              (when (string-match "^\\(.*/\\)\\([^/]+\\)$" file-field)
                (let ((length (- (match-end 2) (match-beginning 2))))
                  (add-text-properties file-point (+ file-point (match-end 1))
                                       (list 'invisible 'yes
                                             'ovirt-log-analyzer-file-field-length length))
                  (setq max-file-field-length (max max-file-field-length length))))
              (dolist (tag tag-list)
                (cond
                 ((string-match "^Task/\\([1-9]\\)$" tag)
                  (ovirt-log-analyzer-add-text (- tag-beg 1) (make-string (string-to-number (match-string 1 tag)) ?>)
                                               'font-lock-keyword-face))
                 ((string-match "^Task(duration=\\([0-9.]+\\))$" tag)
                  (ovirt-log-analyzer-add-text tag-end (concat " " (match-string 1 tag) "s") 'font-lock-constant-face))
                 ((string-match "^Host=\\(.*\\)$" tag)
                  (let ((host (match-string 1 tag)))
                    (add-to-list 'ovirt-log-analyzer-hosts host)
