Skip to content

Commit 92c40a1

Browse files
committed
Move the plugin installatin logic to the configuration
* Enable console and patternMatcher plugins by default * Keep old way to extend the frontend (via plugins/index.js) for BC * Rewrite the plugin documentation
1 parent 34083c3 commit 92c40a1

File tree

8 files changed

+131
-65
lines changed

8 files changed

+131
-65
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Uptime Changelog
44
To be released
55
--------------
66

7+
* Update the README about the plugin system
8+
* Update plugins system to make it easier to enable new plugins, just by adding a line in the configuration
79
* Add pollerCollections to allow the addition of custom pollers
810
* Update HTTP and HTTPS pollers (they now specialize a BaseHttpPoller, to reduce code duplication)
911
* Fix monitor crash when poller is badly set
@@ -15,7 +17,6 @@ To be released
1517
* Add new events to Monitor and dashboard app
1618
* Add more plugins extension points: they can now add details to checks, abilities to pollers, and store additional details about pings
1719
* Move Pattern Matcher logic to a plugin
18-
* Update the README accordingly
1920
* Fix warnings in production by using cookie store for sessions
2021
* Add mention of external plugins in README
2122
* Add pattern detection in response body

README.md

+45-19
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@ Features
1212
--------
1313

1414
* Monitor thousands of websites (powered by [Node.js asynchronous programming](http://dotheweb.posterous.com/nodejs-for-php-programmers-1-event-driven-pro))
15-
* Check the presence of a pattern in the response body
1615
* Tweak frequency of monitoring on a per-check basis, up to the second
17-
* Receive on screen notifications whenever a check goes down (powered by [socket.io](http://socket.io/))
18-
* Receive email notifications whenever a check goes down
16+
* Check the presence of a pattern in the response body
17+
* Receive notifications whenever a check goes down
18+
* On screen (powered by [socket.io](http://socket.io/))
19+
* By email
20+
* On the console
1921
* Record availability statistics for further reporting (powered by [MongoDB](http://www.mongodb.org/))
2022
* Detailed uptime reports with animated charts (powered by [Flotr2](http://www.humblesoftware.com/flotr2/))
2123
* Monitor availability, responsiveness, average response time, and total uptime/downtime
2224
* Get details about failed checks (HTTP error code, etc.)
2325
* Group checks by tags and get reports by tag
2426
* Familiar web interface (powered by [Twitter Bootstrap 2.0](http://twitter.github.com/bootstrap/index.html))
2527
* Complete API for integration with third-party monitoring services
28+
* Powerful plugin system to ease extension and customization
2629
* Easy installation and zero administration
2730

2831
Installing Uptime
@@ -91,6 +94,11 @@ autoStartMonitor: true
9194

9295
server:
9396
port: 8082
97+
98+
plugins:
99+
- ./plugins/console
100+
- ./plugins/patternMatcher
101+
# - ./plugins/email
94102
```
95103

96104
To modify this configuration, create a `development.yaml` or a `production.yaml` file in the same directory, and override just the settings you need. For instance, to run Uptime on port 80 in production, create a `production.yaml` file as follows:
@@ -100,7 +108,7 @@ server:
100108
port: 80
101109
```
102110
103-
Node that Uptime works great behind a proxy - it uses the http_proxy environment variable transparently.
111+
Node that Uptime works great behind a proxy - it uses the `http_proxy` environment variable transparently.
104112

105113
Architecture
106114
------------
@@ -128,37 +136,55 @@ You can even run several monitor servers in several datacenters to get average r
128136
Using Plugins
129137
-------------
130138

131-
Uptime provides plugins that you can enable to add more functionality. Plugins can add more notification types, more poller types, new routes to the webapp, etc. To enable plugins, create a `plugins/index.js` module. Uptime automatically requires this module when starting the webapp and the monitor, and tries to call the two following functions:
139+
Plugins can add more notification types, more poller types, new routes to the webapp, etc. Uptime currently bundles three plugins:
132140

133-
* `initWebApp()` when starting the webapp
134-
* `initMonitor()` when starting the monitor
141+
* [`console`](https://github.com/fzaninotto/uptime/blob/master/plugins/console/index.js): log pings and events in the console in real time
142+
* [`email`](https://github.com/fzaninotto/uptime/blob/master/plugins/email/index.js): notify events (up, down pause) by email
143+
* [`patternMatcher`](https://github.com/fzaninotto/uptime/blob/master/plugins/patternMatcher/index.js): allow HTTP & HTTPS pollers to test the response body against a pattern
135144

136-
For instance, to enable the `console` plugin:
145+
To enable plugins, just add a line to the `plugins:` section of the configuration file.
146+
Two of the bundled plugins are already enabled by default:
137147

138-
```js
139-
// in plugins/index.js
140-
exports.initWebApp = function() {
141-
require('./console').init();
142-
};
148+
```yaml
149+
# in config/default.yaml
150+
plugins:
151+
- ./plugins/console
152+
- ./plugins/patternMatcher
153+
# - ./plugins/email
143154
```
144155

145-
Uptime currently bundles three plugins. Check their documentation for installation/configuration instructions:
156+
You can override these settings in your environment configuration, for instance:
146157

147-
* [`console`](https://github.com/fzaninotto/uptime/blob/master/plugins/console/index.js): log pings and events in the console in real time
148-
* [`email`](https://github.com/fzaninotto/uptime/blob/master/plugins/email/index.js): notify events (up, down pause) by email
149-
* [`patternMatcher`](https://github.com/fzaninotto/uptime/blob/master/plugins/patternMatcher/index.js): allow HTTP & HTTPS pollers to test the response body against a pattern
158+
```yaml
159+
# in config/production.yaml
160+
# disable the console plugin and enable the email plugin
161+
plugins:
162+
# - ./plugins/console
163+
- ./plugins/patternMatcher
164+
- ./plugins/email
165+
```
150166

151167
Third-party plugins:
152168

153169
* [`webhooks`](https://github.com/mintbridge/uptime-webhooks): notify events to an URL by sending an HTTP POST request
154170
* [`campfire`](https://gist.github.com/dmathieu/5592418): notify events to Campfire
155171

156-
You can also create your own plugins. For instance, if you had to recreate a simple version of the `console` plugin, you could write it as follows:
172+
Writing Plugins
173+
---------------
174+
175+
A plugin is a simple Node.js module which hooks into predefined extension points. Uptime automatically requires plugin modules when starting the webapp and the monitor, and tries to call the two following functions:
176+
177+
* `initWebApp(options)` when starting the webapp
178+
* `initMonitor(options)` when starting the monitor
179+
180+
Check the [app.js](https://github.com/fzaninotto/uptime/blob/master/app.js#L97) and [monitor.js](https://github.com/fzaninotto/uptime/blob/master/monitor.js#L8) to see a detail of the options passed to each hook. Also, check the code of existing plugins to understand how they can add new pollers, new notification types, etc.
181+
182+
For instance, if you had to recreate a simple version of the `console` plugin, you could write it as follows:
157183

158184
```js
159185
// in plugins/console/index.js
160186
var CheckEvent = require('../../models/checkEvent');
161-
exports.init = function() {
187+
exports.initWebapp = function() {
162188
CheckEvent.on('afterInsert', function(checkEvent) {
163189
checkEvent.findCheck(function(err, check) {
164190
console.log(new Date() + check.name + checkEvent.isGoDown ? ' goes down' : ' goes back up');

app.js

+14
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,20 @@ io.sockets.on('connection', function(socket) {
9595
});
9696

9797
// load plugins
98+
config.plugins.forEach(function(pluginName) {
99+
var plugin = require(pluginName);
100+
if (typeof plugin.initWebApp !== 'function') return;
101+
console.log('loading plugin %s on app', pluginName);
102+
plugin.initWebApp({
103+
app: app,
104+
api: apiApp, // mounted into app, but required for events
105+
dashboard: dashboardApp, // mounted into app, but required for events
106+
io: io,
107+
config: config,
108+
mongoose: mongoose
109+
});
110+
});
111+
// old way to load plugins, kept for BC
98112
fs.exists('./plugins/index.js', function(exists) {
99113
if (exists) {
100114
var pluginIndex = require('./plugins');

config/default.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ autoStartMonitor: true
2222
server:
2323
port: 8082
2424

25+
plugins:
26+
- ./plugins/console
27+
- ./plugins/patternMatcher
28+
# - ./plugins/email
29+
2530
email:
2631
method: SMTP # possible methods are SMTP, SES, or Sendmail
2732
transport: # see https://github.com/andris9/nodemailer for transport options

monitor.js

+8-10
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ var Monitor = require('./lib/monitor');
66
monitor = Monitor.createMonitor(config.monitor);
77

88
// load plugins
9-
fs.exists('./plugins/index.js', function(exists) {
10-
if (exists) {
11-
var pluginIndex = require('./plugins');
12-
if (typeof pluginIndex.initMonitor === 'function') {
13-
pluginIndex.initMonitor({
14-
monitor: monitor,
15-
config: config
16-
});
17-
}
18-
}
9+
config.plugins.forEach(function(pluginName) {
10+
var plugin = require(pluginName);
11+
if (typeof plugin.initMonitor !== 'function') return;
12+
console.log('loading plugin %s on monitor', pluginName);
13+
plugin.initMonitor({
14+
monitor: monitor,
15+
config: config
16+
});
1917
});
2018

2119
monitor.start();

plugins/console/index.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@
33
*
44
* Logs all pings and events (up, down, paused, restarted) on the console
55
*
6-
* To enable the plugin, call init() in the webapp hook in plugins/index.js
7-
* exports.initWebApp = function() {
8-
* require('./console').init();
9-
* }
10-
*
6+
* Installation
7+
* ------------
8+
* This plugin is enabled by default. To disable it, remove its entry
9+
* from the `plugins` key of the configuration:
10+
*
11+
* // in config/production.yaml
12+
* plugins:
13+
* # - ./plugins/console
1114
*/
1215
var Ping = require('../../models/ping');
1316
var CheckEvent = require('../../models/checkEvent');
1417

15-
exports.init = function(enableNewEvents, enableNewPings) {
18+
exports.initWebApp = function(enableNewEvents, enableNewPings) {
1619
if (typeof enableNewEvents == 'undefined') enableNewEvents = true;
1720
if (typeof enableNewPings == 'undefined') enableNewPings = true;
1821
if (enableNewEvents) registerNewEventsLogger();

plugins/email/index.js

+38-15
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,35 @@
33
*
44
* Notifies all events (up, down, paused, restarted) by email
55
*
6-
* To enable the plugin, call init() in the webapp hook in plugins/index.js
7-
* exports.initWebApp = function() {
8-
* require('./email').init();
9-
* }
6+
* Installation
7+
* ------------
8+
* This plugin is disabled by default. To enable it, add its entry
9+
* to the `plugins` key of the configuration:
1010
*
11-
* Example configuration
11+
* // in config/production.yaml
12+
* plugins:
13+
* - ./plugins/email
14+
*
15+
* Usage
16+
* -----
17+
* This plugin sends an email each time a check is started, goes down, or goes back up.
18+
* When the check goes down, the email contains the error details:
19+
*
20+
* Object: [Down] Check "FooBar" just went down
21+
* On Thursday, September 4th 1986 8:30 PM,
22+
* a test on URL "http://foobar.com" failed with the following error:
23+
*
24+
* Error 500
25+
*
26+
* Uptime won't send anymore emails about this check until it goes back up.
27+
* ---------------------------------------------------------------------
28+
* This is an automated email sent from Uptime. Please don't reply to it.
29+
*
30+
* Configuration
31+
* -------------
32+
* Here is an example configuration:
33+
*
34+
* // in config/production.yaml
1235
* email:
1336
* method: SMTP # possible methods are SMTP, SES, or Sendmail
1437
* transport: # see https://github.com/andris9/nodemailer for transport options
@@ -32,32 +55,32 @@ var moment = require('moment');
3255
var config = require('config').email;
3356
var CheckEvent = require('../../models/checkEvent');
3457
var ejs = require('ejs');
35-
36-
exports.init = function() {
58+
59+
exports.initWebApp = function() {
3760
var mailer = nodemailer.createTransport(config.method, config.transport);
3861
var templateDir = __dirname + '/views/';
3962
CheckEvent.on('afterInsert', function(checkEvent) {
4063
if (!config.event[checkEvent.message]) return;
4164
checkEvent.findCheck(function(err, check) {
4265
if (err) return console.error(err);
4366
var filename = templateDir + checkEvent.message + '.ejs';
44-
var renderOptions = {
45-
check: check,
46-
checkEvent: checkEvent,
47-
url: config.dashboardUrl,
48-
moment: moment,
67+
var renderOptions = {
68+
check: check,
69+
checkEvent: checkEvent,
70+
url: config.dashboardUrl,
71+
moment: moment,
4972
filename: filename
5073
};
5174
var lines = ejs.render(fs.readFileSync(filename, 'utf8'), renderOptions).split('\n');
5275
var mailOptions = {
5376
from: config.message.from,
5477
to: config.message.to,
5578
subject: lines.shift(),
56-
text: lines.join('\n'),
79+
text: lines.join('\n')
5780
};
5881
mailer.sendMail(mailOptions, function(err2, response) {
59-
if (err2) return console.error(err2);
60-
console.log('Notified event by email: Check ' + check.name + ' ' + checkEvent.message);
82+
if (err2) return console.error('Email plugin error: %s', err2);
83+
console.log('Notified event by email: Check ' + check.name + ' ' + checkEvent.message);
6184
});
6285
});
6386
});

plugins/patternMatcher/index.js

+10-14
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,18 @@
33
*
44
* Adds the ability to HTTP & HTTPS pollers to test the response body against a pattern
55
*
6-
* The plugin must be enabled both in the monitor and in the webapp:
6+
* Installation
7+
* ------------
8+
* This plugin is enabled by default. To disable it, remove its entry
9+
* from the `plugins` key of the configuration:
710
*
8-
* // in plugins/index.js
9-
* var patternMatcherPlugin = require('./patternMatcher');
11+
* // in config/production.yaml
12+
* plugins:
13+
* # - ./plugins/patternMatcher
1014
*
11-
* exports.initWebApp = function(options) {
12-
* // enable patternMatcher for the webapp
13-
* patternMatcherPlugin.initWebApp(options);
14-
* };
15-
*
16-
* exports.initMonitor = function(options) {
17-
* // enable patternMatcher for the monitor
18-
* patternMatcherPlugin.initMonitor(options);
19-
* };
20-
*
21-
* Then, restart Uptime, and add a pattern to http checks in the dashboard UI.
15+
* Usage
16+
* -----
17+
* Add a pattern to http checks in the dashboard UI.
2218
* Patterns are regexp, for instance '/hello/i'.
2319
*
2420
* When Uptime polls a check with a pattern, it tests the pattern against the

0 commit comments

Comments
 (0)