#-*- coding: utf-8 -*-fromdjango.confimportsettingsimportthread,threading,time,random,base64,time,os,datetime,gzipfromxml.dom.minidomimportDocumentfromdjango.dbimportconnectionclassLoggingActivities(threading.Thread):""" Author: Julian Moritz, public@julianmoritz.de This middleware is logging the website-activities on your django-project-website. It does NOT save the users' ip-addresses (according to german law) but a unique ID for each user. Once added to your MIDDLEWARE_CLASSES, you can control it via 3 variables in your settings.py: - STATS_LOGDIR - the directory-name where it puts the logfiles into (default: logs) - STATS_BUFFER - the file-buffer-size in bytes for your logfile (default: 10MB) - STATS_TIME - the time the logfile is flushed to disk (default: 12 hours) Note: At the moment there is now import to database and evaluating script written. I will do this in time. License: http://creativecommons.org/licenses/by/2.0/de/deed.en_GB Output: Have a look at http://www.julianmoritz.de/dl/logs.xml """def__init__(self):threading.Thread.__init__(self)try:l=settings.STATS_LOGDIRexcept:l="logs"ifnotos.path.isdir(l):os.mkdir(l)try:b=settings.STATS_BUFFERexcept:b=1024*1024*10try:t=settings.STATS_TIMEexcept:t=60*60*12self.buffer=bself.logdir=lself.time=tself.lock=thread.allocate_lock()self.__rand_id=base64.b64encode(str(random.random()))fname=base64.b64encode(str(random.random()))+".xml"self.logfile=open(os.path.join(self.logdir,fname),"w",self.buffer)self.xmldoc=Document()self.logs=self.xmldoc.createElement("logs")self.xmldoc.appendChild(self.logs)self.start()defprocess_request(self,request):request.STATS={}request.STATS["start"]=datetime.datetime.now()returnNonedefprocess_view(self,request,view,args,kwargs):request.STATS["view_name"]=view.__name__returnNonedefprocess_excepton(self,request,exception):self.log_request(request,exception)returnNonedefprocess_response(self,request,response):self.log_request(request)returnresponsedeflog_request(self,request,exception=None):id=base64.b64encode(str(random.random()))now=int(time.mktime(datetime.datetime.now().timetuple()))try:start=request.STATS["start"]stop=datetime.datetime.now()diff=(stop-start)diffsecs=diff.seconds+diff.microseconds/1000000.except:diffsecs=0.try:view_name=request.STATS["view_name"]except:view_name=""user_agent=request.META["HTTP_USER_AGENT"]user_enc=request.META["HTTP_ACCEPT_ENCODING"]user_lang=request.META["HTTP_ACCEPT_LANGUAGE"]full_path=request.get_full_path()abs_uri=request.build_absolute_uri()query_count=len(connection.queries)user_id=base64.b64encode(self.__rand_id+request.META["REMOTE_ADDR"])ifexception==None:exc_msg=""else:exc_msg=str(exception)xml_dict={"timestamp":now,"user_id":user_id,"duration":diffsecs,"view":view_name,"http_user_agent":user_agent,"http_accept_encoding":user_enc,"http_accept_language":user_lang,"full_path":full_path,"absolute_uri":abs_uri,"query_count":query_count,"exception":exc_msg,}#create xmlself.lock.acquire()log=self.xmldoc.createElement("log")log.setAttribute("id",id)forkinxml_dict:e=self.xmldoc.createElement(k)v=self.xmldoc.createTextNode(str(xml_dict[k]))e.appendChild(v)log.appendChild(e)self.logs.appendChild(log)self.lock.release()defrun(self):while(True):try:#it's bedtime now!time.sleep(self.time)self.lock.acquire()#write xml to fileself.xmldoc.writexml(self.logfile,indent="\t",addindent="\t",newl="\n")#flush and close fileself.logfile.flush()self.logfile.close()#create new empty xml-documentself.xmldoc=Document()self.logs=self.xmldoc.createElement("logs")self.xmldoc.appendChild(self.logs)#create new empty log-fileoldfilename=self.logfile.namefname=base64.b64encode(str(random.random()))+".xml"self.logfile=open(os.path.join(self.logdir,fname),"w",self.buffer)#finished writingself.lock.release()#gzip old file and delete the old xml-filer_file=open(oldfilename,'r')w_file=gzip.GzipFile(oldfilename+'.gz','w',9)w_file.write(r_file.read())w_file.flush()w_file.close()r_file.close()os.unlink(oldfilename)exceptException,e:ifself.lock.locked():self.lock.release()break