├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── lib └── logStream.js ├── package.json └── tests └── LogStreamTests.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | .idea 27 | # Users Environment Variables 28 | .lock-wscript 29 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "stable" 4 | - "4.1" 5 | - "4.0" 6 | - "0.12" 7 | - "iojs" 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Nicolas Traeder traeder@codebility.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bunyan MongoDB Stream 2 | 3 | [![Build Status](https://travis-ci.org/traedamatic/bunyan-mongodb-stream.svg?branch=master)](https://travis-ci.org/traedamatic/bunyan-mongodb-stream) 4 | 5 | A stream implementation for the bunyan logger (https://github.com/trentm/node-bunyan). All log entries will be saved directly to your mongodb 6 | instance. It is a very lower level implementation and has no external dependencies. 7 | 8 | **The implementation requires a mongoose model for saving the log-data in the mongodb instance.** 9 | 10 | # Install 11 | 12 | ``` 13 | npm install bunyan-mongodb-stream 14 | ``` 15 | or 16 | 17 | ``` 18 | npm install bunyan-mongodb-stream --save 19 | ``` 20 | 21 | # How To 22 | 23 | * Install the npm bunyan-mongodb-stream package. ;) 24 | * First to need to create a mongoose model. The package does not include a default model because the schema of the log-entry model may differ 25 | from every use-case the logger will be used. You can add customer fields to mongodb document, just add the field to the schema and pass it to the bunyan logger. More information 26 | custom fields look here: https://github.com/trentm/node-bunyan#log-method-api. The example model includes two custom fields req and res. It is 27 | important that those fields are not required, because not all logger calls will includes those fields. Otherwise the mongodb driver will throw 28 | a validation error. 29 | 30 | 31 | **Example Model** 32 | 33 | ```javascript 34 | 35 | 'use strict'; 36 | var mongoose = require('mongoose'); 37 | 38 | /** 39 | * The schema of the log entry 40 | * @type {Mongoose.Schema} 41 | */ 42 | var LogEntrySchema = new mongoose.Schema({ 43 | msg: { 44 | type: String, 45 | required: true 46 | }, 47 | level: { 48 | type: Number, 49 | required: true 50 | }, 51 | name: { 52 | type: String, 53 | required: true 54 | }, 55 | time: { 56 | type: Date, 57 | required: true 58 | }, 59 | res : { 60 | type: Object 61 | }, 62 | req : { 63 | type: Object 64 | } 65 | }); 66 | 67 | var LogEntryModel = mongoose.model('Log', LogEntrySchema); 68 | ``` 69 | * Require and initialize the bunyan-mongodb-stream package. 70 | 71 | ```javascript 72 | var LogEntryStream = require('bunyan-mongodb-stream')({model: LogEntryModel}); 73 | ``` 74 | 75 | * Set up the bunyan logger and add the LogEntryStream to the streams array. 76 | 77 | ```javascript 78 | 79 | var bunyan = require('bunyan'); 80 | 81 | var logger = bunyan.createLogger({ 82 | name: 'YourLogger', 83 | streams: [ 84 | { 85 | stream: LogEntryStream 86 | } 87 | ], 88 | serializers: bunyan.stdSerializers 89 | }); 90 | 91 | ``` 92 | 93 | * Use the logger as you already do. 94 | 95 | # Further Reading 96 | 97 | * For more details about the bunyan logger go to the github account: https://github.com/trentm/node-bunyan. 98 | * A little gist with a different implementation: https://gist.github.com/oroce/4052571 99 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/logStream'); 2 | -------------------------------------------------------------------------------- /lib/logStream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var stream = require('stream'); 3 | var util = require('util'); 4 | var Writable = stream.Writable; 5 | 6 | /** 7 | * the LogStream constructor. 8 | * it inherits all methods of a writable stream 9 | * the constructor takes a options object. A important field is the model, the model will 10 | * be used for saving the log entry to the mongo db instance. 11 | * @param options 12 | * @constructor 13 | */ 14 | function LogStream(options) { 15 | 16 | this.model = options.model || false; 17 | 18 | if (!this.model) { 19 | throw new Error('[LogStream] - Fatal Error - No mongoose model provided!'); 20 | } 21 | 22 | Writable.call(this, options); 23 | } 24 | 25 | /** 26 | * inherits all Writable Stream methods 27 | */ 28 | util.inherits(LogStream, Writable); 29 | 30 | /** 31 | * the _write method must be overridden by this implementation. 32 | * This method will be called on every write event on this stream. 33 | * @param chunk 34 | * @param enc 35 | * @param cb 36 | * @returns {*} 37 | */ 38 | LogStream.prototype._write = function (chunk, enc, cb) { 39 | 40 | if (this.model === false) { 41 | return cb(); 42 | } 43 | 44 | var newLogEntry = new this.model(JSON.parse(chunk.toString())); 45 | 46 | newLogEntry.save(function (err, logEntry) { 47 | if (err) { 48 | throw err; 49 | } 50 | return cb(); 51 | }) 52 | }; 53 | 54 | /** 55 | * export the logStream 56 | * @param options 57 | * @returns {LogStream} 58 | */ 59 | module.exports = function (options) { 60 | 61 | if (!options) { 62 | options = {}; 63 | } 64 | 65 | return new LogStream(options); 66 | }; 67 | 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bunyan-mongodb-stream", 3 | "version": "0.0.3", 4 | "description": "A database stream for mongoose to save all logs into a mongodb instance", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha tests" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git@github.com:traedamatic/bunyan-mongodb-stream.git" 12 | }, 13 | "keywords": [ 14 | "MongoDb", 15 | "Bunyan", 16 | "Stream", 17 | "Mongoose", 18 | "Database logging", 19 | "Bunyan database logging" 20 | ], 21 | "author": "Nicolas Traeder ", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/traedamatic/bunyan-mongodb-stream/issues" 25 | }, 26 | "homepage": "https://github.com/traedamatic/bunyan-mongodb-stream", 27 | "devDependencies": { 28 | "chai": "^1.9.2", 29 | "mocha": "^2.1.0", 30 | "sinon": "^1.12.2" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/LogStreamTests.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | var logStream = require('./../lib/logStream'); 4 | 5 | /** 6 | * test for the logStream 7 | */ 8 | describe('LogStream', function () { 9 | 10 | describe('Constructor', function () { 11 | 12 | it('should throw a error because no mongoose model is provided', function (done) { 13 | 14 | try { 15 | var newLog = logStream(); 16 | done('Should not pass'); 17 | } catch (e) { 18 | expect(e.message).to.equal('[LogStream] - Fatal Error - No mongoose model provided!'); 19 | done() 20 | } 21 | 22 | }); 23 | 24 | it('should create a logStream instance', function (done) { 25 | var newLog = logStream({model : {}}); 26 | done(); 27 | }); 28 | 29 | 30 | 31 | }); 32 | 33 | describe('_write - method', function () { 34 | 35 | var modelStub, saveStub; 36 | 37 | beforeEach(function (done) { 38 | modelStub = sinon.stub(); 39 | saveStub = sinon.stub(); 40 | modelStub.prototype.save = saveStub; 41 | done(); 42 | }); 43 | 44 | it('should call the save method of the mongoose model', function (done) { 45 | 46 | var newLog = logStream({model : modelStub}); 47 | 48 | newLog._write(new Buffer('{"msg" : "test"}'),'UTF-8', function () { 49 | 50 | }); 51 | 52 | expect(modelStub.called).to.be.true; 53 | expect(saveStub.called).to.be.true; 54 | expect(modelStub.calledBefore(saveStub)).to.be.true; 55 | 56 | done(); 57 | 58 | 59 | }); 60 | 61 | }) 62 | }); --------------------------------------------------------------------------------