The output log file via Ajax in Django

I followed the accepted SO answer on how to read the log file in Django from / var / log / gateway from here , and I was able to output the file to the terminal, like here.

2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up... 2013-05-09T12:57:44.160246+08:00 localhost gateway[5205]: System start complete. 2013-05-09T15:13:47.428553+08:00 localhost gateway[4777]: * Unable to connect to device /home/smartsensor1. Device may be offline. * 

Next step: I want to output the log file and display it in html, I did this with a little modification of the source code like this.

 def Logs(request): with open('../../../../../var/log/gateway') as f: while True: line = f.readline() if line: print line return HttpResponse(line) 

So, on the client side, I put Ajax like this, based on another answer we accepted here .

 $.ajax({ type: "GET", url : "{% url WebServiceApp.logging.Logs %}", success: function (data) { $("#output").append(data); setTimeout("doUpdate()", 2000); } }); } setTimeout("doUpdate()", 2000); 

The Ajax output is saved when the first line of the log file is displayed. Where in this case, like this

 2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up... 2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up... 2013-05-09T11:15:02.539091+08:00 localhost gateway[5205]: System starting up... 

I know this happens because every time ajax goes to the server, the server does what it needs and sends back the output, which is the first line of the log file and output via HttpResponse, and it completes the loop, and it does did not get the opportunity to make another line, because it is already completed. When another request is executed, it does the same thing again and again.

Thus, a possible solution is a client that requests the server once, and the server continues to display the log file line by line and send it to the client. I'm not sure if this is possible, so I ask any expert on how to possibly achieve a result, where I can output the log file by line /

+4
source share
2 answers

I found a way to solve this by running the Server-Sent event

On the server side, I use django-sse , which depends on sse

 import os from django.conf import settings from django.views.generic import View from django_sse.views import BaseSseView import time from django.utils.timezone import now from datetime import datetime from django.utils.timezone import now from dateutil import parser class MySseEvents(BaseSseView): def iterator(self): while True: if not os.path.exists('/var/log/gateway'): file('/var/log/gateway', 'w+').close() with open('/var/log/gateway') as f: while True: #get the current time currenttime = now() #read a line from gateway line = f.readline() if line: #split the line read into 4 section str = line.split(' ',3) #compare if the time from the log file is less than the current time logtime = parser.parse(str[0]) if logtime >= currenttime: #print when the log is written after the current time output = '%s: %s' % (datetime.strftime(logtime,'%d/%m %H:%M %p'), str[3]) self.sse.add_message("line", output) time.sleep(1) yield 

Checking if logtime >= currenttime: which I did above is to make sure that html prints logs only after loading the page, not the entire log file.

Then, on the HTML5 side, I made a similar example, shown by the author in the first link I provided.

 <div id="tab9" class="tab_content"> <table> <tr> <td> <p> Shows the records of the logs on gateway.</p> <div style="border:1px solid; height: 200px; width: 850px; overflow: auto;" id="output"></div> </td> </tr> </table> </div> <script> $(document).ready(function() { var source = new EventSource('/gtwy/logging/'); var events_dom = $("#output"); source.addEventListener("line", function(e) { events_dom.append(e.data + "<br>"); }); }); </script> 

Using this, I was able to display the log as it is available. The only problem I am facing is creating the gateway file itself, which requires permission, because I'm trying to create it in /var/log .

0
source

Well, you can use this idea:

Using the GET parameters, you can control the viewing method as follows:

 def Logs(request): whole_file = True if request.GET.get('whole_file') == 0: whole_file = False return_string = '' with open('../../../../../var/log/gateway') as f: while True: line = f.readline() if line: return_string += line + '<br>' # <br> is for breakline html, do it your way if not whole_file: break # break if you only need first line return HttpResponse(line) 

So you include a variable inside the get parameter that tells your view whether to return the entire log file (first time) or only the first line (next time).

Then in your ajax you will need to specify a way to insert GET parameters into url. You are using the {{url}} tag, I’m not quite sure how to do this with it, but I’m sure that you will find something in the document if you cannot try another approach, for example a static string (not very nice) or create your own tag for it.

This will be an example of your possible javascript:

 $.ajax({ type: "GET", url : "/ajax_log/?whole_file=0", //this will request the whole file success: function (data) { $("#output").append(data); setTimeout("doUpdate()", 2000); } }); } setTimeout("doNextUpdate()", 2000); function doNextUpdate(){ $.ajax({ type: "GET", url : "/ajax_log/?whole_file=1", //this will request the just the first line success: function (data) { $("#output").append(data); setTimeout("doUpdate()", 2000); } }); } } 

It is my idea to accomplish what you want. Hope this helps.

0
source

Source: https://habr.com/ru/post/1480016/


All Articles