Changes that bring CLASH up to extended HTTP/1.0 support:
Added simple common logging file format mixin and a simple profiling mixin. This is more for demonstration purposes, than for real-life usage. Real world appliations will probably want to do their own customized forms of logging and/or profiling.
This commit is contained in:
109
src/main/logging.cl
Normal file
109
src/main/logging.cl
Normal file
@ -0,0 +1,109 @@
|
||||
;;;; CLASH --- The Common Lisp Adaptable Simple HTTP server
|
||||
;;;; This is copyrighted software. See documentation for terms.
|
||||
;;;;
|
||||
;;;; logging.cl --- Logging and tracing functionality
|
||||
;;;;
|
||||
;;;; Checkout Tag: $Name$
|
||||
;;;; $Id$
|
||||
|
||||
(in-package :CLASH)
|
||||
|
||||
;;;; %File Description:
|
||||
;;;;
|
||||
;;;;
|
||||
;;;;
|
||||
|
||||
(defclass server-profiling-mixin ()
|
||||
((connection-count :initform 0
|
||||
:accessor server-profiling-mixin-connection-count)
|
||||
(connection-time :initform 0
|
||||
:accessor server-profiling-mixin-connection-time)
|
||||
(connection-min :initform most-positive-fixnum
|
||||
:accessor server-profiling-mixin-connection-min)
|
||||
(connection-max :initform 0
|
||||
:accessor server-profiling-mixin-connection-max)
|
||||
(request-count :initform 0
|
||||
:accessor server-profiling-mixin-request-count)
|
||||
(request-time :initform 0
|
||||
:accessor server-profiling-mixin-request-time)
|
||||
(request-min :initform most-positive-fixnum
|
||||
:accessor server-profiling-mixin-request-min)
|
||||
(request-max :initform 0
|
||||
:accessor server-profiling-mixin-request-max)))
|
||||
|
||||
(defmethod server-profiling-mixin-connection-avg ((server server-profiling-mixin))
|
||||
(/ (server-profiling-mixin-connection-time server)
|
||||
(server-profiling-mixin-connection-count server)))
|
||||
|
||||
(defmethod server-profiling-mixin-request-avg ((server server-profiling-mixin))
|
||||
(/ (server-profiling-mixin-request-time server)
|
||||
(server-profiling-mixin-request-count server)))
|
||||
|
||||
(defmethod serve-connection :around
|
||||
((server server-profiling-mixin) connection)
|
||||
(let ((start (get-internal-real-time)))
|
||||
(multiple-value-prog1 (call-next-method)
|
||||
(let ((delay (- (get-internal-real-time) start)))
|
||||
(incf (server-profiling-mixin-connection-time server) delay)
|
||||
(incf (server-profiling-mixin-connection-count server))
|
||||
(setf (server-profiling-mixin-connection-min server)
|
||||
(min (server-profiling-mixin-connection-min server) delay)
|
||||
(server-profiling-mixin-connection-max server)
|
||||
(max (server-profiling-mixin-connection-max server) delay))))))
|
||||
|
||||
(defmethod serve-request :around ((server server-profiling-mixin) request)
|
||||
(let ((start (get-internal-real-time)))
|
||||
(multiple-value-prog1 (call-next-method)
|
||||
(let ((delay (- (get-internal-real-time) start)))
|
||||
(incf (server-profiling-mixin-request-time server) delay)
|
||||
(incf (server-profiling-mixin-request-count server))
|
||||
(setf (server-profiling-mixin-request-min server)
|
||||
(min (server-profiling-mixin-request-min server) delay)
|
||||
(server-profiling-mixin-request-max server)
|
||||
(max (server-profiling-mixin-request-max server) delay))))))
|
||||
|
||||
(defclass server-logging-mixin ()
|
||||
((pathname :initarg :pathname :accessor server-logging-mixin-pathname)
|
||||
(stream :accessor server-logging-mixin-stream)))
|
||||
|
||||
(defmethod initialize-instance :after
|
||||
((instance server-logging-mixin) &rest args)
|
||||
(declare (ignore args))
|
||||
(unless (slot-boundp instance 'stream)
|
||||
(setf (server-logging-mixin-stream instance)
|
||||
(open (server-logging-mixin-pathname instance)
|
||||
:direction :output
|
||||
:if-exists :append :if-does-not-exist :create))))
|
||||
|
||||
(defmethod (setf server-logging-mixin-pathname) :before
|
||||
(new (instance server-logging-mixin))
|
||||
(when (slot-boundp instance 'stream)
|
||||
(close (server-logging-mixin-stream instance))))
|
||||
|
||||
(defmethod (setf server-logging-mixin-pathname) :after
|
||||
(new (instance server-logging-mixin))
|
||||
(setf (server-logging-mixin-stream instance)
|
||||
(open (server-logging-mixin-pathname instance)
|
||||
:direction :output
|
||||
:if-exists :append :if-does-not-exist :create)))
|
||||
|
||||
(defmethod write-response :after
|
||||
((server server-logging-mixin) connection response)
|
||||
(let ((stream (server-logging-mixin-stream server)))
|
||||
(multiple-value-bind (second minute hour date month year day daylight-p
|
||||
zone)
|
||||
(get-decoded-time)
|
||||
(declare (ignore daylight-p day))
|
||||
(ignore-errors
|
||||
(format stream
|
||||
"~A - - [~2,'0D/~2,'0D/~4,'0D:~2,'0D:~2,'0D:~2,'0D ~@4,'0D] \"~A ~A ~A\" ~3,'0D ~D~%"
|
||||
(connection-hostname connection)
|
||||
date month year hour minute second (* zone 100)
|
||||
(request-method (response-request response))
|
||||
(request-url (response-request response))
|
||||
(http-message-version (response-request response))
|
||||
(response-status-code response)
|
||||
(let ((entity (http-message-entity response)))
|
||||
(if entity
|
||||
(or (entity-content-length entity) 0)
|
||||
0)))))))
|
||||
Reference in New Issue
Block a user