Hello list,

I am trying to wrap my mind around AJAX, and I would like to solicit your advice. I have made something that can do real time (well... almost :) ) log file monitoring, but I don't see how to implement it in the most web2pythonic way possible.

In the controller I have a function "getlog()". It can be any function as long as it returns something suitable for display on an html page. Here it is showing the last 10 lines of a file, formatted in an html table.

I also have a factory function make_log_component which takes a filepath, an _id, _class and refresh_period argument. This factory function returns a div that can be embedded in a view, and can be styled via CSS (through its _id and _class attributes). By giving a unique _id you can embed multiple independent log file monitors in the same page.

As you can see this is using not many of the web2py ajax provisions.

What would be the "correct" way of implementing this using the web2py constructs like LOAD, web2py_ajax, ...? How could this be wrapped in a web2py component?

Thanks in advance for any insights you may have,
Stefaan.

The code: (I hope the indentation won't be screwed up)

Controller default.py:

def getlog():
   """
   function that provides the content that should be auto-updated
   as an example: the tail of a log file
   """
   filepath = request.vars['filepath']
   import os.path
   if not os.path.isfile(filepath):
       return ["ERROR: File %s not found." % filepath]

   def tail(filepath, nol=10, read_size=1024):
       """
       This function returns the last line of a file.
       Args:
         filepath: path to file
         nol: number of lines to print
read_size: data is read in chunks of this size (optional, default=1024)
       """
       try:
f = open(filepath, 'rU') # U is to open it with Universal newline support
       except IOError:
return ["ERROR: File %s could not be opened for reading. Check the permissions." % filepath]
       offset = read_size
       f.seek(0, 2)
       file_size = f.tell()
       while 1:
          if file_size < offset:
             offset = file_size
          f.seek(-1*offset, 2)
          read_str = f.read(offset)
          # Remove newline at the end
          if read_str[offset - 1] == '\n':
             read_str = read_str[:-1]
          lines = read_str.split('\n')
          if len(lines) >= nol:  # Got nol lines
             result = lines[-nol:]
             f.close()
             return result
          if offset == file_size:   # Reached the beginning
             f.close()
             return read_str.split("\n")
          offset += read_size

       f.close()
       return [""]

   table = [  [l] for l in tail(filepath) ]
   return TABLE(*[TR(*rows) for rows in table])

def make_log_component(filepath, logprovder, _id="log", _class="", refresh_period=1000):
    url = URL(logprovider)
    LogComponent = DIV(SCRIPT("""
      jQuery(document).ready(
          function()
          {
              jQuery("#%(id)s").load("%(url)s");
              var refreshId = setInterval(
                 function()
                 {

jQuery("#%(id)s").load("%(url)s?filepath=%(filepath)s");
                 },
                 %(refresh)d);
          });
""" % {'url' : url, 'id' : _id, 'refresh' : refresh_period, 'filepath' : filepath } ),
          DIV(_id=_id,_class=_class))
    return LogComponent

def index():
    return dict(
LOGCOMPONENT1=make_log_component("/path/to/log.txt", getlog, _id="logcomp1", _class="log", refresh_period=1000), LOGCOMPONENT2=make_log_component("/path/to/otherlog.txt", getlog, _id="logcomp2", _class="log", refresh_period=500),
    )


view /default/index.html (trying out two file monitors simultaneously):

{{extend 'layout.html'}}

<table>
<tr>
    <th>Log Component 1</th> <th>Log Component 2</th>
</tr>
<tr>
    <td>{{=LOGCOMPONENT1}}</td> <td>{{=LOGCOMPONENT2}}</td>
</tr>
</table>

Reply via email to