Permalink
Browse files

Improved structure between monitor application and main application.

  • Loading branch information...
1 parent a38167e commit 2f07cd34ed470d34f0929ae557a3d3ee79163720 @jbohman committed Jun 9, 2010
View
@@ -9,5 +9,7 @@ cassandra_port: 9160
# List of paths (files and directories) to monitor
paths:
- - /var/log/:
- recursive: True
+ - name: ~/coding/cassandra/access.log
+ recursive: False
+ - name: /var/log/testing/
+ recurisve: True
View
@@ -3,17 +3,40 @@
import os
import optparse
import time
+import multiprocessing
+import logging
# Local imports
+import monitor
import config
+import utils
from utils.daemon import Daemon
class Application(Daemon):
+ def monitor(self):
+ reader = monitor.Reader(False)
+ watcher = monitor.Watcher(self.settings['paths'], reader.callback)
+ watcher.loop()
+
# TODO: setup application here, monitor + pylon webservice
def run(self):
- while 1:
+
+ # Setup logging
+ logging.basicConfig(filename=self.settings['logfile_name'], level=logging.DEBUG)
+
+ # Test to see if settings is present
+ if not hasattr(self, 'settings'):
+ print 'No settings, exiting...'
+ sys.exit(1)
+
+ # Start monitor process
+ self.monitor_process = multiprocessing.Process(target=self.monitor)
+ self.monitor_process.start()
+
+ self.running = True
+ while self.running:
time.sleep(10)
@@ -28,11 +51,18 @@ def run(self):
parser.add_option('--config-file', dest='config_file', metavar='FILE', default=default_config_file)
parser.add_option('--working-directory', dest='working_directory', metavar='DIRECTORY', default=default_working_directory)
parser.add_option('--pid-file', dest='pid_file', metavar='FILE', default='/tmp/logsandra.pid')
+ parser.add_option('--application-data-directory', dest='application_data_directory', default=utils.application_data_directory('logsandra'))
(options, args) = parser.parse_args()
- settings = config.parse(options.config_file)
- application = Application(options.pid_file)
- application.settings = settings
+ if not os.path.isdir(options.application_data_directory):
+ os.makedirs(options.application_data_directory)
+
+ output_file = os.path.join(options.application_data_directory, 'logsandra.log')
+
+ application = Application(options.pid_file, stdout=output_file, stderr=output_file)
+ application.settings = config.parse(options.config_file)
+ application.settings['application_data_directory'] = options.application_data_directory
+ application.settings['logfile_name'] = output_file
if len(args) == 1:
if args[0] == 'start':
@@ -42,10 +72,11 @@ def run(self):
elif args[0] == 'restart':
application.restart()
else:
- print "Unknown command"
+ print 'Unknown command'
sys.exit(2)
sys.exit(0)
else:
- print parser.get_usage()
- sys.exit(2)
+ application.run()
+ #print parser.get_usage()
+ #sys.exit(2)
@@ -0,0 +1 @@
+from monitor import Reader, Watcher
@@ -4,10 +4,10 @@
from optparse import OptionParser
# Try to import pyinotify handler, else standard handler
-try:
- from watchers.inotify import InotifyWatcher as Watcher
-except ImportError:
- from watchers.standard import StandardWatcher as Watcher
+#try:
+# from watchers.inotify import InotifyWatcher as Watcher
+#except ImportError:
+from watchers.standard import StandardWatcher as Watcher
class Reader(object):
@@ -42,7 +42,7 @@ def callback(self, filename):
usage = 'usage: %prog [options] path [path ...]'
parser = OptionParser(usage=usage)
parser.add_option('-r', '--rescan-freq', dest='rescan_freq', help='rescan frequency in seconds', metavar='SECONDS', default=20)
- parser.add_option('-u', '--update-freq', dest='update_freq', help='update frequnecy in seconds', metavar='SECONDS', default=0)
+ parser.add_option('-u', '--update-freq', dest='update_freq', help='update frequnecy in seconds', metavar='SECONDS', default=10)
parser.add_option('-t', '--tail', action='store_true', dest='tail', help='start reading from the bottom only', default=False)
parser.add_option('--recursive', action='store_true', dest='recursive')
(options, args) = parser.parse_args()
@@ -51,12 +51,10 @@ def callback(self, filename):
print "Need atleast one path (file or directory) to monitor, see --help"
sys.exit(1)
- settings = {'freq': options.update_freq, 'rescan': options.rescan_freq}
-
entities = []
for arg in args:
- entities.append({'name': args, 'recursive': options.recursive})
+ entities.append({'name': arg, 'recursive': options.recursive})
r = Reader(options.tail)
- w = Watcher(settings, entities, r.callback)
+ w = Watcher(entities, r.callback, update_freq=options.update_freq, rescan_freq=options.rescan_freq)
w.loop()
@@ -9,16 +9,18 @@ def process_IN_MODIFY(self, event):
class InotifyWatcher(object):
- def __init__(self, settings, entities, callback):
- self.settings = settings
+ def __init__(self, entities, callback, update_freq=0, rescan_freq=20):
+ self.update_freq = update_freq
+ self.rescan_freq = rescan_freq
+
self.entities = entities
self.callback = lambda x: callback(x.pathname)
self.wm = pyinotify.WatchManager()
pyinotify.log.setLevel(50)
def loop(self):
- notifier = pyinotify.Notifier(self.wm, EventHandler(callback=self.callback), self.settings['freq'])
+ notifier = pyinotify.Notifier(self.wm, EventHandler(callback=self.callback), self.update_freq)
for entity in self.entities:
self.wm.add_watch(entity['name'], pyinotify.IN_MODIFY, rec=entity['recursive'])
@@ -4,10 +4,13 @@
class StandardWatcher(object):
- def __init__(self, settings, entities, callback):
- self.settings = settings
+ def __init__(self, entities, callback, update_freq=10, rescan_freq=20):
+ self.update_freq = update_freq
+ self.rescan_freq = rescan_freq
+
self.entities = entities
self.callback = callback
+
self.files = {}
for filename in self._find_files_generator():
@@ -18,7 +21,7 @@ def __init__(self, settings, entities, callback):
def loop(self):
while True:
current_time = time.time()
- if (current_time - self._last_rescan_time) > self.settings['rescan']:
+ if (current_time - self._last_rescan_time) > self.rescan_freq:
self._last_rescan_time = self._rescan()
reference_time = time.time()
@@ -28,9 +31,9 @@ def loop(self):
self.files[filename] = new_mtime
self.callback(filename)
- if self.settings['freq'] > 0:
+ if self.update_freq > 0:
current_time = time.time()
- sleep = self.settings['freq'] - (current_time - reference_time)
+ sleep = self.update_freq - (current_time - reference_time)
if sleep > 0:
time.sleep(sleep)
@@ -51,8 +54,11 @@ def _find_files_generator(self):
yield filename
# Is file
else:
- filename = os.path.join(os.path.abspath(entity['name']), entity['name'])
- yield filename
+ if os.path.exists(os.path.expanduser(entity['name'])):
+ filename = os.path.abspath(os.path.expanduser(entity['name']))
+ yield filename
+ else:
+ raise AttributeError('Invalid path, cannot monitor it')
def _rescan(self):
tempfiles = {}
@@ -73,11 +79,3 @@ def _mtime(self, filename):
return os.stat(filename).st_mtime
except os.error:
return False
-
-
-if __name__ == '__main__':
- def callback(x):
- print x
-
- sw = StandardWatcher({'freq': 1, 'rescan': 10}, [{'name': '.', 'recursive': False}], callback)
- sw.loop()
@@ -0,0 +1,12 @@
+import sys
+import os
+
+def application_data_directory(appname):
+ if sys.platform == 'darwin':
+ from AppKit import NSSearchPathForDirectoriesInDomains
+ appdata = path.join(NSSearchPathForDirectoriesInDomains(14, 1, True)[0], appname)
+ elif sys.platform == 'win32':
+ appdata = os.path.join(os.environ['APPDATA'], appname)
+ else:
+ appdata = os.path.expanduser(os.path.join("~", "." + appname))
+ return appdata
@@ -9,7 +9,7 @@
import atexit
from signal import SIGTERM
-class Daemon:
+class Daemon(object):
"""
A generic daemon class.

0 comments on commit 2f07cd3

Please sign in to comment.