Ori.livneh has uploaded a new change for review.
https://gerrit.wikimedia.org/r/74303
Change subject: Load plug-in data sinks from preconfigured location
......................................................................
Load plug-in data sinks from preconfigured location
This patch allows EventLogging to be extended using plug-ins. Plug-ins are
Python scripts that register data readers/writers using the @reads and @writes
decorators provided in eventlogging.factory. If these Python scripts are placed
in /usr/lib/eventlogging (overrideable by setting EVENTLOGGING_PLUGIN_DIR in
the environment), they will be auto-loaded by eventlogging-consumer, unless
'--no-plugins' is specified on the command line.
Change-Id: Ia5f9d9979e740ef903be2611fb482e1849aec16d
---
M server/bin/eventlogging-consumer
M server/eventlogging/handlers.py
A server/tests/plugins/mock.py
M server/tests/test_handlers.py
4 files changed, 54 insertions(+), 2 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/EventLogging
refs/changes/03/74303/1
diff --git a/server/bin/eventlogging-consumer b/server/bin/eventlogging-consumer
index 3e527d7..e58abf4 100755
--- a/server/bin/eventlogging-consumer
+++ b/server/bin/eventlogging-consumer
@@ -13,7 +13,8 @@
output-uri URI of output stream
optional arguments:
- -h, --help show this help message and exit
+ -h, --help show this help message and exit
+ --no-plugins run without loading plug-ins
:copyright: (c) 2012 by Ori Livneh <[email protected]>
:license: GNU General Public Licence 2.0 or later
@@ -36,8 +37,14 @@
fromfile_prefix_chars='@')
ap.add_argument('input', help='URI of raw input stream')
ap.add_argument('output', help='URI of output stream', default='stdout://')
+ap.add_argument('--no-plugins', help='run without loading plug-ins',
+ action='store_false', dest='load_plugins')
+ap.set_defaults(load_plugins=True)
args = ap.parse_args()
+if args.load_plugins:
+ eventlogging.load_plugins()
+
log.info('Driving %s -> %s..', args.input, args.output)
while 1:
try:
diff --git a/server/eventlogging/handlers.py b/server/eventlogging/handlers.py
index e974225..8717da6 100644
--- a/server/eventlogging/handlers.py
+++ b/server/eventlogging/handlers.py
@@ -11,10 +11,13 @@
"""
import datetime
+import glob
+import imp
import io
import json
import logging
import logging.handlers
+import os
import socket
import sys
@@ -27,6 +30,23 @@
from .jrm import store_sql_event
+__all__ = ('load_plugins',)
+
+#: EventLogging will attempt to load the configuration file specified in the
+#: 'EVENTLOGGING_PLUGIN_DIR' environment variable if it is defined. If it is
+#: not defined, EventLogging will default to the value specified below.
+DEFAULT_PLUGIN_DIR = '/usr/lib/eventlogging'
+
+
+def load_plugins(path=None):
+ """Load EventLogging plug-ins from `path`. Plug-in module names are mangled
+ to prevent clobbering modules in the Python module search path."""
+ if path is None:
+ path = os.environ.get('EVENTLOGGING_PLUGIN_DIR', DEFAULT_PLUGIN_DIR)
+ for plugin in glob.glob(os.path.join(path, '*.py')):
+ imp.load_source('__eventlogging_plugin_%x__' % hash(plugin), plugin)
+
+
# Mappers
@mapper
diff --git a/server/tests/plugins/mock.py b/server/tests/plugins/mock.py
new file mode 100644
index 0000000..8399ac7
--- /dev/null
+++ b/server/tests/plugins/mock.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+from eventlogging.factory import reads
+
+@reads('mock')
+def mock_writer():
+ """A mock EventLogging writer used for testing the plug-in auto-loader."""
+ while 1:
+ yield 'value generated by plug-in'
diff --git a/server/tests/test_handlers.py b/server/tests/test_handlers.py
index 8f95a25..dc16752 100644
--- a/server/tests/test_handlers.py
+++ b/server/tests/test_handlers.py
@@ -3,14 +3,16 @@
eventlogging unit tests
~~~~~~~~~~~~~~~~~~~~~~~
- This module contains tests for :module:`eventlogging.jrm`.
+ This module contains tests for :module:`eventlogging.handlers`.
"""
from __future__ import unicode_literals
+import os
import unittest
import eventlogging
+import eventlogging.handlers
import eventlogging.factory
@@ -48,3 +50,18 @@
"""``get_reader`` returns the right generator for the URI scheme."""
reader = eventlogging.get_reader('test://localhost/?value=secret')
self.assertEqual(next(reader), 'secret')
+
+
+class PluginTestCase(unittest.TestCase):
+ """Test case for the plug-in loader."""
+
+ def setUp(self):
+ """Determine path to mock plugin directory."""
+ script_path = os.path.dirname(os.path.abspath(__file__))
+ self.plugin_path = os.path.join(script_path, 'plugins')
+
+ def test_load_plugins(self):
+ """`get_plugins` loads plug-ins from an arbitrary path."""
+ eventlogging.handlers.load_plugins(self.plugin_path)
+ reader = eventlogging.get_reader('mock://localhost')
+ self.assertEqual(next(reader), 'value generated by plug-in')
--
To view, visit https://gerrit.wikimedia.org/r/74303
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia5f9d9979e740ef903be2611fb482e1849aec16d
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/EventLogging
Gerrit-Branch: master
Gerrit-Owner: Ori.livneh <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits