UNPKG

4.92 kBJavaScriptView Raw
1'use strict';
2
3var R = require('ramda');
4var util = require('util');
5var events = require('events');
6var fs = require('fs-extra');
7var gs = require('goldwasher-schedule');
8var cs = require('chronostore');
9var bunyan = require('bunyan');
10var BunyanToLoggly = require('bunyan-loggly').Bunyan2Loggly;
11var BunyanToSlack = require('bunyan-slack');
12var logentries = require('le_node');
13var log;
14
15function getSettings(settings) {
16 var result;
17
18 if (R.is(Object, settings)) {
19 result = settings;
20 } else {
21 result = fs.readJsonSync(settings || './sitesampler.json');
22 }
23
24 if (!result.targets || !R.isArrayLike(result.targets) || result.targets.length < 1) {
25 throw new Error('No targets provided. Remember to set settings.targets.');
26 }
27
28 if (typeof result.rethrowErrors === 'undefined') {
29 result.rethrowErrors = true;
30 }
31
32 return result;
33}
34
35function getLogglyLogger() {
36 var loggly = {
37 'token': process.env['SITESAMPLER_LOGGLY_TOKEN'],
38 'subdomain': process.env['SITESAMPLER_LOGGLY_SUBDOMAIN'],
39 'level': process.env['SITESAMPLER_LOGGLY_LEVEL'] || 'info'
40 };
41
42 if (loggly.token && loggly.subdomain) {
43 return {
44 'level': loggly.level,
45 'type': 'raw',
46 'stream': new BunyanToLoggly(loggly)
47 };
48 }
49}
50
51function getSlackLogger() {
52 var slack = {
53 'webhook_url': process.env['SITESAMPLER_SLACK_WEBHOOKURL'],
54 'channel': process.env['SITESAMPLER_SLACK_CHANNEL'] || null,
55 'level': process.env['SITESAMPLER_SLACK_LEVEL'] || 'info',
56 'username': process.env['SITESAMPLER_SLACK_USERNAME'] || 'sitesampler'
57 };
58
59 if (slack.webhook_url) {
60 return {
61 'level': slack.level,
62 'stream': new BunyanToSlack(slack)
63 };
64 }
65}
66
67function getLogentriesLogger() {
68 var logger = {
69 'token': process.env['SITESAMPLER_LOGENTRIES_TOKEN']
70 };
71
72 if (logger.token) {
73 return logentries.bunyanStream(logger);
74 }
75}
76
77function setupLogger(enabled) {
78 if (enabled) {
79 var logger = {
80 'name': 'sitesampler',
81 'streams': [{'level': 'info', 'stream': process.stdout}]
82 };
83
84 var loggly = getLogglyLogger();
85 if (loggly) {
86 logger.streams.push(loggly);
87 }
88
89 var slack = getSlackLogger();
90 if (slack) {
91 logger.streams.push(slack);
92 }
93
94 var logentries = getLogentriesLogger();
95 if (logentries) {
96 logger.streams.push(logentries);
97 }
98
99 log = bunyan.createLogger(logger);
100
101 log.info('Logging enabled.');
102
103 if (loggly) {
104 log.info('Loggly enabled.');
105 }
106
107 if (slack) {
108 log.info('Slack enabled.');
109 }
110
111 if (logentries) {
112 log.info('Logentries enabled.');
113 }
114
115 } else {
116 log = bunyan.createLogger({'name': 'testing', 'streams': []});
117 }
118}
119
120var SiteSampler = function(settingsPathOrObject) {
121 var self = this;
122 var settings = getSettings(settingsPathOrObject);
123
124 setupLogger(process.env['SITESAMPLER_LOG']);
125
126 log.info('Setting up sitesampler...');
127
128 self.gs = gs(settings.targets, settings.options);
129
130 self.gs.on('running', function(options) {
131 log.info(options, 'Sitesampler running.');
132 });
133
134 self.gs.on('result', function(results, options) {
135 options.ms = options.end - options.start;
136 log.info(options, 'Result from ' + options.url + ' in ' + options.ms + ' ms.');
137 self.writeToDisk(results, options, settings);
138 });
139
140 self.gs.on('error', function(error, options) {
141 log.error(error, 'Error with results from goldwasher for "' + options.url + '". Aborting write.');
142 if (settings.rethrowErrors) {
143 self.emit('error', error);
144 }
145 });
146
147 events.EventEmitter.call(this);
148 log.info('Setup completed.');
149};
150
151util.inherits(SiteSampler, events.EventEmitter);
152
153SiteSampler.prototype.start = function() {
154 var self = this;
155
156 setImmediate(function() {
157 log.info('Starting sitesampler.');
158 self.emit('start');
159 });
160
161 self.gs.start();
162
163 return self;
164};
165
166SiteSampler.prototype.stop = function() {
167 var self = this;
168
169 log.info('Stopping sitesampler.');
170 self.emit('stop');
171
172 self.gs.stop();
173
174 return self;
175};
176
177SiteSampler.prototype.writeToDisk = function(results, options, settings) {
178 var self = this;
179
180 if (results.length > 0) {
181 log.info({'url': options.url}, 'Writing results to chronostore...');
182
183 cs.objectToStream(results)
184 .pipe(cs.writeObject(settings.chronostore))
185 .on('error', function(error) {
186 log.error(error, 'Error when writing results to chronostore for "' + options.url + '".');
187 if (settings.rethrowErrors) {
188 self.emit('error', error);
189 }
190 })
191 .on('finish', function() {
192 log.info({'url': options.url}, 'Write to chronostore completed.');
193 self.emit('results', results, options);
194 });
195 } else {
196 log.warn({'target': options}, 'No results from goldwasher. Aborting write.');
197 self.emit('results', results, options);
198 }
199};
200
201
202module.exports = function(settingsPathOrObject) {
203 return new SiteSampler(settingsPathOrObject);
204};