Skip to content

veliovgroup/Meteor-logger-mongo

support support

Logging: To MongoDB

MongoDB adapter for logger driver. Store application's logs and messages in MongoDB.

Whenever you log message(s) on Client or Sever, it goes directly into MongoDB.

Features:

  • πŸ‘·β€β™‚οΈ 100% tests coverage;
  • πŸ’ͺ Flexible log level filters;
  • πŸ‘¨β€πŸ’» userId is automatically passed and logged, data is associated with logged-in user;
  • πŸ“Ÿ Pass logs from Client to MongoDB on Server;
  • πŸ•· Catch all browser's errors and exceptions.

Installation:

meteor add ostrio:logger # If not yet installed
meteor add ostrio:loggermongo

ES6 Import:

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

Usage

Initialize Logger instance and pass it into LoggerMongo constructor to enable logging into the log file.

Initialization [Isomorphic]

new LoggerMongo(LoggerInstance, options)

  • LoggerInstance {Logger} - from new Logger()
  • options {Object}
  • options.collection {Mongo.Collection} - Use to pass your own MongoDB collection instance, {Mongo.Collection} returned from new Mongo.Collection()
  • options.collectionName {String} - MongoDB collection name, default: ostrioMongoLogger
  • options.format {Function} - Must return plain object, which will be used as log-record. Arguments:
    • opts {Object}
    • opts.userId {String}
    • opts.date {Date} - Report date
    • opts.timestamp {Number} - Report timestamp in milliseconds
    • opts.level {String} - Message level, one of: ERROR, FATAL, WARN, DEBUG, INFO, TRACE, *
    • opts.message {String} - Report message
    • opts.additional {Object} - Additional info passed as object

Note: You can't pass both collection and collectionName simultaneously. Set only one of those options. If both options is presented collection is more prioritized

Example:

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

// Initialize Logger:
const log = new Logger();

// Initialize and enable LoggerMongo with default settings:
(new LoggerMongo(log)).enable();

Example 2:

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

// Initialize Logger:
const log = new Logger();
const appLogs = new Mongo.Collection('appLogs');

// Initialize LoggerMongo with collection instance:
const logMongo = new LoggerMongo(log, {
  collection: appLogs
});

// Enable LoggerMongo with default settings:
logMongo.enable();

Example 3:

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

// Initialize Logger:
const log = new Logger();

// Initialize LoggerMongo with custom collection name:
const logMongo = new LoggerMongo(log, {
  collectionName: 'appLogs'
});

// Enable LoggerMongo with default settings:
logMongo.enable();

Initialize with custom adapter settings: [Isomorphic]

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

const log = new Logger();
(new LoggerMongo(log)).enable({
  enable: true,
  filter: ['ERROR', 'FATAL', 'WARN'], // Filters: 'ERROR', 'FATAL', 'WARN', 'DEBUG', 'INFO', 'TRACE', '*'
  client: true, // Set to `false` to avoid Client to Server logs transfer
  server: true  // Allow logging on Server
});

Logging Collection Schema:

({
  userId: {
    type: String
  },
  date: {
    type: Date
  },
  timestamp: {
    type: Number
  },
  level: {
    type: String
  },
  message: {
    type: String
  },
  additional: {  // <- passed object into 'data' argument
    type: Object // upon logging will be available for search
  }
});

Set custom indexes on collection: [Server]

Read more at: ensureIndex docs

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

const log = new Logger();
const logMongo = new LoggerMongo(log, {
  collectionName: 'appLogs' // Use custom collection name
});

if (Meteor.isServer) {
  // PRECAUTION: make sure you understand what you're doing and why
  // Do not ever blindly copy-paste, see: https://github.com/veliovgroup/Meteor-logger-mongo/issues/19
  logMongo.collection._ensureIndex({level: 1}, {background: true});
  logMongo.collection._ensureIndex({userId: 1}, {background: true});
  logMongo.collection._ensureIndex({date: 1}, {background: true});
  logMongo.collection._ensureIndex({timestamp: 1}, {background: true});
}

Log message: [Isomorphic]

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

const log = new Logger();
(new LoggerMongo(log)).enable();

/*
  message {String} - Any text message
  data    {Object} - [optional] Any additional info as object
  userId  {String} - [optional] Current user id
 */
log.info(message, data, userId);
log.debug(message, data, userId);
log.error(message, data, userId);
log.fatal(message, data, userId);
log.warn(message, data, userId);
log.trace(message, data, userId);
log._(message, data, userId); // Shortcut

// Use with throw
throw log.error(message, data, userId);

Catch-all Client's errors example: [Client]

/* Store original window.onerror */
const _GlobalErrorHandler = window.onerror;

window.onerror = function (msg, url, line) {
  log.error(msg, {file: url, onLine: line});
  if (_GlobalErrorHandler) {
    _GlobalErrorHandler.apply(this, arguments);
  }
};

Catch-all Server's errors example: [Server]

const bound = Meteor.bindEnvironment((callback) => {callback();});
process.on('uncaughtException', function (err) {
  bound(() => {
    log.error('Server Crashed!', err);
    console.error(err.stack);
    process.exit(7);
  });
});

Catch-all Meteor's errors example: [Server]

// store original Meteor error
const originalMeteorDebug = Meteor._debug;
Meteor._debug = function (message, stack) {
  const additional = { message };
  additional.stack = util.inspect(stack, false, null).split('\n');
  log.error('Meteor Error!', additional);
  return originalMeteorDebug.apply(this, arguments);
};

Use multiple logger(s) with different settings: [Isomorphic]

import { Logger } from 'meteor/ostrio:logger';
import { LoggerMongo } from 'meteor/ostrio:loggermongo';

const log1 = new Logger();
const log2 = new Logger();

/*
 * Separate settings and collection
 * for info, debug and other messages
 */
(new LoggerMongo(log1, {
  collectionName: 'appLogs'
})).enable({
  filter: ['DEBUG', 'INFO', 'LOG', 'TRACE'],
  client: true,
  server: true
});

/*
 * Separate settings and collection
 * for errors, exceptions, warnings and etc.
 */
(new LoggerMongo(log2, {
  collectionName: 'AppErrors'
})).enable({
  filter: ['ERROR', 'FATAL', 'WARN'],
  client: true,
  server: true
});

Running Tests

  1. Clone this package
  2. In Terminal (Console) go to directory where package is cloned
  3. Then run:

Meteor/Tinytest

meteor test-packages ./

Support this awesome package:

Support our open source contribution: