diff --git a/doc/DEPLOYMENT.md b/doc/DEPLOYMENT.md index 46253724..dba03a95 100644 --- a/doc/DEPLOYMENT.md +++ b/doc/DEPLOYMENT.md @@ -43,7 +43,9 @@ The app role can contain any of the following units. You may distribute them as * [rethinkdb-proxy-28015.service](#rethinkdb-proxy-28015service) * [stf-app@.service](#stf-appservice) * [stf-auth@.service](#stf-authservice) +* [stf-log-rethinkdb.service](#stf-log-rethinkdbservice) * [stf-migrate.service](#stf-migrateservice) +* [stf-notify-hipchat.service](#stf-notify-hipchatservice) * [stf-processor@.service](#stf-processorservice) * [stf-provider@.service](#stf-providerservice) * [stf-reaper.service](#stf-reaperservice) @@ -53,7 +55,6 @@ The app role can contain any of the following units. You may distribute them as * [stf-triproxy-app.service](#stf-triproxy-appservice) * [stf-triproxy-dev.service](#stf-triproxy-devservice) * [stf-websocket@.service](#stf-websocketservice) -* [stf-notify-hipchat.service](#stf-notify-hipchatservice) ### Proxy role @@ -505,6 +506,36 @@ ExecStop=/usr/bin/docker stop -t 10 %p-%i These units are optional and don't affect the way STF works in any way. +### `stf-log-rethinkdb.service` + +**Requires** the `rethinkdb-proxy-28015.service` unit on the same host. + +Allows you to store device log events into RethinkDB. + +Note that it doesn't make sense to have more than one instance of this unit running at once as you'd just record the same events twice. + +```ini +[Unit] +Description=STF RethinkDB log recorder +After=rethinkdb-proxy-28015.service +BindsTo=rethinkdb-proxy-28015.service + +[Service] +EnvironmentFile=/etc/environment +TimeoutStartSec=0 +Restart=always +ExecStartPre=/usr/bin/docker pull openstf/stf:latest +ExecStartPre=-/usr/bin/docker kill %p +ExecStartPre=-/usr/bin/docker rm %p +ExecStart=/usr/bin/docker run --rm \ + --name %p \ + --link rethinkdb-proxy-28015:rethinkdb \ + openstf/stf:latest \ + stf log-rethinkdb \ + --connect-sub tcp://appside.stf.example.org:7150 +ExecStop=-/usr/bin/docker stop -t 10 %p +``` + ### `stf-notify-hipchat.service` If you use [HipChat](https://www.hipchat.com/), you can use this unit to push notifications to your room. Check `stf notify-hipchat --help` for more configuration options. diff --git a/lib/cli.js b/lib/cli.js index a6e2d95f..3fc921a5 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -539,6 +539,29 @@ program }) }) +program + .command('log-rethinkdb') + .description('start a rethinkdb log recorder') + .option('-p, --priority ' + , 'minimum log level' + , Number + , logger.Level.DEBUG) + .option('-s, --connect-sub ' + , 'sub endpoint' + , cliutil.list) + .action(function(options) { + if (!options.connectSub) { + this.missingArgument('--connect-sub') + } + + require('./units/log/rethinkdb')({ + priority: options.priority + , endpoints: { + sub: options.connectSub + } + }) + }) + program .command('poorxy') .description('start a poor reverse proxy for local development') diff --git a/lib/units/log/rethinkdb.js b/lib/units/log/rethinkdb.js new file mode 100644 index 00000000..94215b5c --- /dev/null +++ b/lib/units/log/rethinkdb.js @@ -0,0 +1,52 @@ +var Promise = require('bluebird') +var zmq = require('zmq') + +var logger = require('../../util/logger') +var wire = require('../../wire') +var wirerouter = require('../../wire/router') +var wireutil = require('../../wire/util') +var lifecycle = require('../../util/lifecycle') +var srv = require('../../util/srv') +var dbapi = require('../../db/api') + +module.exports = function(options) { + var log = logger.createLogger('log-db') + + // Input + var sub = zmq.socket('sub') + Promise.map(options.endpoints.sub, function(endpoint) { + return srv.resolve(endpoint).then(function(records) { + return srv.attempt(records, function(record) { + log.info('Receiving input from "%s"', record.url) + sub.connect(record.url) + return Promise.resolve(true) + }) + }) + }) + + // Establish always-on channels + ;[wireutil.global].forEach(function(channel) { + log.info('Subscribing to permanent channel "%s"', channel) + sub.subscribe(channel) + }) + + sub.on('message', wirerouter() + .on(wire.DeviceLogMessage, function(channel, message) { + if (message.priority >= options.priority) { + dbapi.saveDeviceLog(message.serial, message) + } + }) + .handler()) + + log.info('Listening for %s (or higher) level log messages', + logger.LevelLabel[options.priority]) + + lifecycle.observe(function() { + try { + sub.close() + } + catch (err) { + // No-op + } + }) +} diff --git a/lib/units/processor/index.js b/lib/units/processor/index.js index d2546e77..de11f7fa 100644 --- a/lib/units/processor/index.js +++ b/lib/units/processor/index.js @@ -139,7 +139,6 @@ module.exports = function(options) { appDealer.send([channel, data]) }) .on(wire.DeviceLogMessage, function(channel, message, data) { - dbapi.saveDeviceLog(message.serial, message) appDealer.send([channel, data]) }) .on(wire.DeviceIdentityMessage, function(channel, message, data) {