Skip to content

Commit

Permalink
Merge 002c4c2 into a67ad42
Browse files Browse the repository at this point in the history
  • Loading branch information
alecgibson committed Nov 15, 2018
2 parents a67ad42 + 002c4c2 commit 1c3a9cf
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 11 deletions.
43 changes: 43 additions & 0 deletions README.md
Expand Up @@ -182,6 +182,28 @@ share.addProjection('users_limited', 'users', { name:true, profileUrl:true });

Note that only the [JSON0 OT type](https://github.com/ottypes/json0) is supported for projections.

### Logging

By default, ShareDB logs to `console`. This can be overridden if you wish to silence logs, or to log to your own logging driver or alert service.

Methods can be overridden by passing a [`console`-like object](https://developer.mozilla.org/en-US/docs/Web/API/console) to `Backend`:

```javascript
var share = new Backend({
logger: {
info: () => {}, // Silence info
warn: () => alerts.warn(arguments), // Forward warnings to alerting service
error: () => alerts.critical(arguments) // Remap errors to critical alerts
}
});
```

ShareDB only supports the following logger methods:

- `info`
- `warn`
- `error`

### Shutdown

`share.close(callback)`
Expand Down Expand Up @@ -358,6 +380,27 @@ after a sequence of diffs are handled.
`query.on('extra', function() {...}))`
(Only fires on subscription queries) `query.extra` changed.

### Logging

By default, ShareDB logs to `console`. This can be overridden if you wish to silence logs, or to log to your own logging driver or alert service.

Methods can be overridden by passing a [`console`-like object](https://developer.mozilla.org/en-US/docs/Web/API/console) to `logger.setMethods`

```javascript
var ShareDB = require('sharedb/lib/client');
ShareDB.logger.setMethods({
info: () => {}, // Silence info
warn: () => alerts.warn(arguments), // Forward warnings to alerting service
error: () => alerts.critical(arguments) // Remap errors to critical alerts
});
```

ShareDB only supports the following logger methods:

- `info`
- `warn`
- `error`


## Error codes

Expand Down
9 changes: 5 additions & 4 deletions lib/agent.js
@@ -1,6 +1,7 @@
var hat = require('hat');
var util = require('./util');
var types = require('./types');
var logger = require('./logger');

/**
* Agent deserializes the wire protocol messages received from the stream and
Expand Down Expand Up @@ -47,7 +48,7 @@ module.exports = Agent;
// Close the agent with the client.
Agent.prototype.close = function(err) {
if (err) {
console.warn('Agent closed due to error', this.clientId, err.stack || err);
logger.warn('Agent closed due to error', this.clientId, err.stack || err);
}
if (this.closed) return;
// This will end the writable stream and emit 'finish'
Expand Down Expand Up @@ -95,7 +96,7 @@ Agent.prototype._subscribeToStream = function(collection, id, stream) {
// Log then silently ignore errors in a subscription stream, since these
// may not be the client's fault, and they were not the result of a
// direct request by the client
console.error('Doc subscription stream error', collection, id, data.error);
logger.error('Doc subscription stream error', collection, id, data.error);
return;
}
if (agent._isOwnOp(collection, data)) return;
Expand Down Expand Up @@ -137,7 +138,7 @@ Agent.prototype._subscribeToQuery = function(emitter, queryId, collection, query
// Log then silently ignore errors in a subscription stream, since these
// may not be the client's fault, and they were not the result of a
// direct request by the client
console.error('Query subscription stream error', collection, query, err);
logger.error('Query subscription stream error', collection, query, err);
};

emitter.onOp = function(op) {
Expand Down Expand Up @@ -195,7 +196,7 @@ Agent.prototype._reply = function(request, err, message) {
};
} else {
if (err.stack) {
console.warn(err.stack);
logger.warn(err.stack);
}
request.error = {
code: err.code,
Expand Down
3 changes: 3 additions & 0 deletions lib/backend.js
Expand Up @@ -2,6 +2,7 @@ var async = require('async');
var Agent = require('./agent');
var Connection = require('./client/connection');
var emitter = require('./emitter');
var logger = require('./logger');
var MemoryDB = require('./db/memory');
var NoOpMilestoneDB = require('./milestone-db/no-op');
var MemoryPubSub = require('./pubsub/memory');
Expand Down Expand Up @@ -40,6 +41,8 @@ function Backend(options) {
this.agentsCount = 0;
this.remoteAgentsCount = 0;

logger.setMethods(options.logger);

// The below shims are for backwards compatibility. These options will be
// removed in a future major version
if (!options.disableDocAction) {
Expand Down
11 changes: 6 additions & 5 deletions lib/client/connection.js
Expand Up @@ -5,6 +5,7 @@ var emitter = require('../emitter');
var ShareDBError = require('../error');
var types = require('../types');
var util = require('../util');
var logger = require('../logger');

function connectionState(socket) {
if (socket.readyState === 0 || socket.readyState === 1) return 'connecting';
Expand Down Expand Up @@ -116,11 +117,11 @@ Connection.prototype.bindToSocket = function(socket) {
var data = (typeof event.data === 'string') ?
JSON.parse(event.data) : event.data;
} catch (err) {
console.warn('Failed to parse message', event);
logger.warn('Failed to parse message', event);
return;
}

if (connection.debug) console.log('RECV', JSON.stringify(data));
if (connection.debug) logger.info('RECV', JSON.stringify(data));

var request = {data: data};
connection.emit('receive', request);
Expand Down Expand Up @@ -252,7 +253,7 @@ Connection.prototype.handleMessage = function(message) {
return;

default:
console.warn('Ignoring unrecognized message', message);
logger.warn('Ignoring unrecognized message', message);
}
};

Expand All @@ -274,7 +275,7 @@ Connection.prototype._handleBulkMessage = function(message, method) {
if (doc) doc[method](message.error);
}
} else {
console.error('Invalid bulk message', message);
logger.error('Invalid bulk message', message);
}
};

Expand Down Expand Up @@ -426,7 +427,7 @@ Connection.prototype.sendOp = function(doc, op) {
* Sends a message down the socket
*/
Connection.prototype.send = function(message) {
if (this.debug) console.log('SEND', JSON.stringify(message));
if (this.debug) logger.info('SEND', JSON.stringify(message));

this.emit('send', message);
this.socket.send(JSON.stringify(message));
Expand Down
3 changes: 2 additions & 1 deletion lib/client/doc.js
@@ -1,4 +1,5 @@
var emitter = require('../emitter');
var logger = require('../logger');
var ShareDBError = require('../error');
var types = require('../types');

Expand Down Expand Up @@ -832,7 +833,7 @@ Doc.prototype._opAcknowledged = function(message) {
} else if (message.v !== this.version) {
// We should already be at the same version, because the server should
// have sent all the ops that have happened before acknowledging our op
console.warn('Invalid version from server. Expected: ' + this.version + ' Received: ' + message.v, message);
logger.warn('Invalid version from server. Expected: ' + this.version + ' Received: ' + message.v, message);

// Fetching should get us back to a working document state
return this.fetch();
Expand Down
1 change: 1 addition & 0 deletions lib/client/index.js
Expand Up @@ -3,3 +3,4 @@ exports.Doc = require('./doc');
exports.Error = require('../error');
exports.Query = require('./query');
exports.types = require('../types');
exports.logger = require('../logger');
3 changes: 3 additions & 0 deletions lib/logger/index.js
@@ -0,0 +1,3 @@
var Logger = require('./logger');
var logger = new Logger();
module.exports = logger;
21 changes: 21 additions & 0 deletions lib/logger/logger.js
@@ -0,0 +1,21 @@
var SUPPORTED_METHODS = [
'info',
'warn',
'error'
];

function Logger() {
this.setMethods(console);
}
module.exports = Logger;

Logger.prototype.setMethods = function (overrides) {
overrides = overrides || {};
var logger = this;

SUPPORTED_METHODS.forEach(function (method) {
if (typeof overrides[method] === 'function') {
logger[method] = overrides[method];
}
});
};
3 changes: 2 additions & 1 deletion lib/stream-socket.js
@@ -1,5 +1,6 @@
var Duplex = require('stream').Duplex;
var inherits = require('util').inherits;
var logger = require('./logger');
var util = require('./util');

function StreamSocket() {
Expand Down Expand Up @@ -36,7 +37,7 @@ function ServerStream(socket) {
this.socket = socket;

this.on('error', function(error) {
console.warn('ShareDB client message stream error', error);
logger.warn('ShareDB client message stream error', error);
socket.close('stopped');
});

Expand Down
46 changes: 46 additions & 0 deletions test/logger.js
@@ -0,0 +1,46 @@
var Logger = require('../lib/logger/logger');
var expect = require('expect.js');
var sinon = require('sinon');

describe('Logger', function () {
describe('Stubbing console.warn', function () {
beforeEach(function () {
sinon.stub(console, 'warn');
});

afterEach(function () {
sinon.restore();
});

it('logs to console by default', function () {
var logger = new Logger();
logger.warn('warning');
expect(console.warn.calledOnceWithExactly('warning')).to.be(true);
});

it('overrides console', function () {
var customWarn = sinon.stub();
var logger = new Logger();
logger.setMethods({
warn: customWarn
});

logger.warn('warning');

expect(console.warn.notCalled).to.be(true);
expect(customWarn.calledOnceWithExactly('warning')).to.be(true);
});

it('only overrides if provided with a method', function () {
var badWarn = 'not a function';
var logger = new Logger();
logger.setMethods({
warn: badWarn
});

logger.warn('warning');

expect(console.warn.calledOnceWithExactly('warning')).to.be(true);
});
});
});

0 comments on commit 1c3a9cf

Please sign in to comment.