Browse Source

site log command updated

bugfixes
harshadyeola 10 years ago
parent
commit
6a742abee8
  1. 10
      ee/cli/plugins/site.py
  2. 66
      ee/cli/plugins/site_functions.py
  3. 192
      ee/core/logwatch.py

10
ee/cli/plugins/site.py

@ -106,10 +106,10 @@ class EESiteController(CementBaseController):
@expose(help="Monitor example.com logs")
def log(self):
(ee_domain, ee_www_domain) = ValidateDomain(self.app.pargs.site_name)
ee_site_webroot = EEVariables.ee_webroot + ee_domain
if os.path.isfile('/etc/nginx/sites-available/{0}'
.format(ee_domain)):
EEShellExec.cmd_exec(self, 'tail -f /var/log/nginx/{0}.*.log'
.format(ee_domain))
logwatch(self, ee_site_webroot + '/logs/')
else:
Log.error(self, " site {0} does not exists".format(ee_domain))
@ -457,6 +457,8 @@ class EESiteCreateController(CementBaseController):
" {0}".format(ee_wp_creds['wp_user']))
Log.info(self, Log.ENDC + "WordPress admin user password : {0}"
.format(ee_wp_creds['wp_pass']))
display_cache_settings(self, data)
addNewSite(self, ee_www_domain, stype, cache, ee_site_webroot)
Log.info(self, "Successfully created site"
" http://{0}".format(ee_domain))
@ -900,7 +902,7 @@ class EESiteUpdateController(CementBaseController):
" {0}".format(ee_wp_creds['wp_user']))
Log.info(self, Log.ENDC + "WordPress admin password : {0}"
.format(ee_wp_creds['wp_pass']) + "\n\n")
display_cache_settings(self, data)
updateSiteInfo(self, ee_www_domain, stype=stype, cache=cache)
Log.info(self, "Successfully updated site"
" http://{0}".format(ee_domain))
@ -916,7 +918,7 @@ class EESiteDeleteController(CementBaseController):
(['site_name'],
dict(help='domain name to be deleted')),
(['--no-prompt'],
dict(help="dont ask for permission for delete",
dict(help="doesnt ask permission for delete",
action='store_true')),
(['--all'],
dict(help="delete all", action='store_true')),

66
ee/cli/plugins/site_functions.py

@ -433,3 +433,69 @@ def updatewpuserpassword(self, ee_domain, ee_site_webroot):
else:
Log.error(self, "Invalid WordPress user {0} for {1}."
.format(ee_wp_user, ee_domain))
def display_cache_settings(self, data):
if data['wpsc']:
if data['multisite']:
Log.info(self, "Configure WPSC:"
"\t\thttp://{0}/wp-admin/network/settings.php?"
"page=wpsupercache"
.format(data['site_name']))
else:
Log.info(self, "Configure WPSC:"
"\t\thttp://{0}/wp-admin/options-general.php?"
"page=wpsupercache"
.format(data['site_name']))
if data['wpfc']:
if data['multisite']:
Log.info(self, "Configure nginx-helper:"
"\thttp://{0}/wp-admin/network/settings.php?"
"page=nginx".format(data['site_name']))
else:
Log.info(self, "Configure nginx-helper:"
"\thttp://{0}/wp-admin/options-general.php?"
"page=nginx".format(data['site_name']))
if data['wpfc'] or data['w3tc']:
if data['multisite']:
Log.info(self, "Configure W3TC:"
"\t\thttp://{0}/wp-admin/network/admin.php?"
"page=w3tc_general".format(data['site_name']))
else:
Log.info(self, "Configure W3TC:"
"\t\thttp://{0}wp-admin/admin.php?"
"page=w3tc_general".format(data['site_name']))
if data['wpfc']:
Log.info(self, "Page Cache:\t\tDisable")
elif data['w3tc']:
Log.info(self, "Page Cache:\t\tDisk Enhanced")
Log.info(self, "Database Cache:\t\tMemcached")
Log.info(self, "Object Cache:\t\tMemcached")
Log.info(self, "Browser Cache:\t\tDisable")
def logwatch(self, logdir):
import zlib
import base64
import time
from ee.core import logwatch
def callback(filename, lines):
for line in lines:
if line.find(':::') == -1:
print(line)
else:
data = line.split(':::')
try:
print(data[0], data[1],
zlib.decompress(base64.decodestring(data[2])))
except Exception as e:
Log.info(time.time(),
'caught exception rendering a new log line in %s'
% filename)
l = logwatch.LogWatcher(logdir, callback)
l.loop()

192
ee/core/logwatch.py

@ -0,0 +1,192 @@
"""
Real time log files watcher supporting log rotation.
"""
import os
import time
import errno
import stat
from ee.core.logging import Log
class LogWatcher(object):
"""Looks for changes in all files of a directory.
This is useful for watching log file changes in real-time.
It also supports files rotation.
Example:
>>> def callback(filename, lines):
... print filename, lines
...
>>> l = LogWatcher("/var/www/example.com/logs", callback)
>>> l.loop()
"""
def __init__(self, folder, callback, extensions=["log"], tail_lines=0):
"""Arguments:
(str) @folder:
the folder to watch
(callable) @callback:
a function which is called every time a new line in a
file being watched is found;
this is called with "filename" and "lines" arguments.
(list) @extensions:
only watch files with these extensions
(int) @tail_lines:
read last N lines from files being watched before starting
"""
self.files_map = {}
self.callback = callback
self.folder = os.path.realpath(folder)
self.extensions = extensions
assert (os.path.isdir(self.folder), "%s does not exists"
% self.folder)
assert callable(callback)
self.update_files()
# The first time we run the script we move all file markers at EOF.
# In case of files created afterwards we don't do this.
for id, file in list(iter(self.files_map.items())):
file.seek(os.path.getsize(file.name)) # EOF
if tail_lines:
lines = self.tail(file.name, tail_lines)
if lines:
self.callback(file.name, lines)
def __del__(self):
self.close()
def loop(self, interval=0.1, async=False):
"""Start the loop.
If async is True make one loop then return.
"""
while 1:
self.update_files()
for fid, file in list(iter(self.files_map.items())):
self.readfile(file)
if async:
return
time.sleep(interval)
def log(self, line):
"""Log when a file is un/watched"""
print(line)
def listdir(self):
"""List directory and filter files by extension.
You may want to override this to add extra logic or
globbling support.
"""
ls = os.listdir(self.folder)
if self.extensions:
return ([x for x in ls if os.path.splitext(x)[1][1:]
in self.extensions])
else:
return ls
@staticmethod
def tail(fname, window):
"""Read last N lines from file fname."""
try:
f = open(fname, 'r')
except IOError as err:
if err.errno == errno.ENOENT:
return []
else:
raise
else:
BUFSIZ = 1024
f.seek(0, os.SEEK_END)
fsize = f.tell()
block = -1
data = ""
exit = False
while not exit:
step = (block * BUFSIZ)
if abs(step) >= fsize:
f.seek(0)
exit = True
else:
f.seek(step, os.SEEK_END)
data = f.read().strip()
if data.count('\n') >= window:
break
else:
block -= 1
return data.splitlines()[-window:]
def update_files(self):
ls = []
for name in self.listdir():
absname = os.path.realpath(os.path.join(self.folder, name))
try:
st = os.stat(absname)
except EnvironmentError as err:
if err.errno != errno.ENOENT:
raise
else:
if not stat.S_ISREG(st.st_mode):
continue
fid = self.get_file_id(st)
ls.append((fid, absname))
# check existent files
for fid, file in list(iter(self.files_map.items())):
# next(iter(graph.items()))
try:
st = os.stat(file.name)
except EnvironmentError as err:
if err.errno == errno.ENOENT:
self.unwatch(file, fid)
else:
raise
else:
if fid != self.get_file_id(st):
# same name but different file (rotation); reload it.
self.unwatch(file, fid)
self.watch(file.name)
# add new ones
for fid, fname in ls:
if fid not in self.files_map:
self.watch(fname)
def readfile(self, file):
lines = file.readlines()
if lines:
self.callback(file.name, lines)
def watch(self, fname):
try:
file = open(fname, "r")
fid = self.get_file_id(os.stat(fname))
except EnvironmentError as err:
if err.errno != errno.ENOENT:
raise
else:
self.log("watching logfile %s" % fname)
self.files_map[fid] = file
def unwatch(self, file, fid):
# file no longer exists; if it has been renamed
# try to read it for the last time in case the
# log rotator has written something in it.
lines = self.readfile(file)
self.log("un-watching logfile %s" % file.name)
del self.files_map[fid]
if lines:
self.callback(file.name, lines)
@staticmethod
def get_file_id(st):
return "%xg%x" % (st.st_dev, st.st_ino)
def close(self):
for id, file in list(iter(self.files_map.items())):
file.close()
self.files_map.clear()
Loading…
Cancel
Save