Giter Site home page Giter Site logo

winston's Introduction

winston

A logger for just about everything.

Version npm npm Downloads build status coverage status

NPM

winston@3

See the Upgrade Guide for more information. Bug reports and PRs welcome!

Looking for [email protected] documentation?

Please note that the documentation below is for winston@3. Read the [email protected] documentation.

Motivation

winston is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs. Each winston logger can have multiple transports (see: Transports) configured at different levels (see: Logging levels). For example, one may want error logs to be stored in a persistent remote location (like a database), but all logs output to the console or a local file.

winston aims to decouple parts of the logging process to make it more flexible and extensible. Attention is given to supporting flexibility in log formatting (see: Formats) & levels (see: Using custom logging levels), and ensuring those APIs decoupled from the implementation of transport logging (i.e. how the logs are stored / indexed, see: Adding Custom Transports) to the API that they exposed to the programmer.

Quick Start

TL;DR? Check out the quick start example in ./examples/. There are a number of other examples in ./examples/*.js. Don't see an example you think should be there? Submit a pull request to add it!

Usage

The recommended way to use winston is to create your own logger. The simplest way to do this is using winston.createLogger:

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'user-service' },
  transports: [
    //
    // - Write all logs with importance level of `error` or less to `error.log`
    // - Write all logs with importance level of `info` or less to `combined.log`
    //
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple(),
  }));
}

You may also log directly via the default logger exposed by require('winston'), but this merely intended to be a convenient shared logger to use throughout your application if you so choose. Note that the default logger doesn't have any transports by default. You need add transports by yourself, and leaving the default logger without any transports may produce a high memory usage issue.

Table of contents

Logging

Logging levels in winston conform to the severity ordering specified by RFC5424: severity of all levels is assumed to be numerically ascending from most important to least important.

const levels = {
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  verbose: 4,
  debug: 5,
  silly: 6
};

Creating your own Logger

You get started by creating a logger using winston.createLogger:

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

A logger accepts the following parameters:

Name Default Description
level 'info' Log only if info.level is less than or equal to this level
levels winston.config.npm.levels Levels (and colors) representing log priorities
format winston.format.json Formatting for info messages (see: Formats)
transports [] (No transports) Set of logging targets for info messages
exitOnError true If false, handled exceptions will not cause process.exit
silent false If true, all logs are suppressed

The levels provided to createLogger will be defined as convenience methods on the logger returned.

//
// Logging
//
logger.log({
  level: 'info',
  message: 'Hello distributed log files!'
});

logger.info('Hello again distributed logs');

You can add or remove transports from the logger once it has been provided to you from winston.createLogger:

const files = new winston.transports.File({ filename: 'combined.log' });
const console = new winston.transports.Console();

logger
  .clear()          // Remove all transports
  .add(console)     // Add console transport
  .add(files)       // Add file transport
  .remove(console); // Remove console transport

You can also wholesale reconfigure a winston.Logger instance using the configure method:

const logger = winston.createLogger({
  level: 'info',
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

//
// Replaces the previous transports with those in the
// new configuration wholesale.
//
const DailyRotateFile = require('winston-daily-rotate-file');
logger.configure({
  level: 'verbose',
  transports: [
    new DailyRotateFile(opts)
  ]
});

Creating child loggers

You can create child loggers from existing loggers to pass metadata overrides:

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
  ]
});

const childLogger = logger.child({ requestId: '451' });

.child is likely to be bugged if you're also extending the Logger class, due to some implementation details that make this keyword to point to unexpected things. Use with caution.

Streams, objectMode, and info objects

In winston, both Logger and Transport instances are treated as objectMode streams that accept an info object.

The info parameter provided to a given format represents a single log message. The object itself is mutable. Every info must have at least the level and message properties:

const info = {
  level: 'info',                 // Level of the logging message
  message: 'Hey! Log something?' // Descriptive message being logged.
};

Properties besides level and message are considered as "meta". i.e.:

const { level, message, ...meta } = info;

Several of the formats in logform itself add additional properties:

Property Format added by Description
splat splat() String interpolation splat for %d %s-style messages.
timestamp timestamp() timestamp the message was received.
label label() Custom label associated with each message.
ms ms() Number of milliseconds since the previous log message.

As a consumer you may add whatever properties you wish – internal state is maintained by Symbol properties:

  • Symbol.for('level') (READ-ONLY): equal to level property. Is treated as immutable by all code.
  • Symbol.for('message'): complete string message set by "finalizing formats":
    • json
    • logstash
    • printf
    • prettyPrint
    • simple
  • Symbol.for('splat'): additional string interpolation arguments. Used exclusively by splat() format.

These Symbols are stored in another package: triple-beam so that all consumers of logform can have the same Symbol reference. i.e.:

const { LEVEL, MESSAGE, SPLAT } = require('triple-beam');

console.log(LEVEL === Symbol.for('level'));
// true

console.log(MESSAGE === Symbol.for('message'));
// true

console.log(SPLAT === Symbol.for('splat'));
// true

NOTE: any { message } property in a meta object provided will automatically be concatenated to any msg already provided: For example the below will concatenate 'world' onto 'hello':

logger.log('error', 'hello', { message: 'world' });
logger.info('hello', { message: 'world' });

Formats

Formats in winston can be accessed from winston.format. They are implemented in logform, a separate module from winston. This allows flexibility when writing your own transports in case you wish to include a default format with your transport.

In modern versions of node template strings are very performant and are the recommended way for doing most end-user formatting. If you want to bespoke format your logs, winston.format.printf is for you:

const { createLogger, format, transports } = require('winston');
const { combine, timestamp, label, printf } = format;

const myFormat = printf(({ level, message, label, timestamp }) => {
  return `${timestamp} [${label}] ${level}: ${message}`;
});

const logger = createLogger({
  format: combine(
    label({ label: 'right meow!' }),
    timestamp(),
    myFormat
  ),
  transports: [new transports.Console()]
});

To see what built-in formats are available and learn more about creating your own custom logging formats, see logform.

Combining formats

Any number of formats may be combined into a single format using format.combine. Since format.combine takes no opts, as a convenience it returns pre-created instance of the combined format.

const { createLogger, format, transports } = require('winston');
const { combine, timestamp, label, prettyPrint } = format;

const logger = createLogger({
  format: combine(
    label({ label: 'right meow!' }),
    timestamp(),
    prettyPrint()
  ),
  transports: [new transports.Console()]
})

logger.log({
  level: 'info',
  message: 'What time is the testing at?'
});
// Outputs:
// { level: 'info',
//   message: 'What time is the testing at?',
//   label: 'right meow!',
//   timestamp: '2017-09-30T03:57:26.875Z' }

String interpolation

The log method provides the string interpolation using util.format. It must be enabled using format.splat().

Below is an example that defines a format with string interpolation of messages using format.splat and then serializes the entire info message using format.simple.

const { createLogger, format, transports } = require('winston');
const logger = createLogger({
  format: format.combine(
    format.splat(),
    format.simple()
  ),
  transports: [new transports.Console()]
});

// info: test message my string {}
logger.log('info', 'test message %s', 'my string');

// info: test message 123 {}
logger.log('info', 'test message %d', 123);

// info: test message first second {number: 123}
logger.log('info', 'test message %s, %s', 'first', 'second', { number: 123 });

Filtering info Objects

If you wish to filter out a given info Object completely when logging then simply return a falsey value.

const { createLogger, format, transports } = require('winston');

// Ignore log messages if they have { private: true }
const ignorePrivate = format((info, opts) => {
  if (info.private) { return false; }
  return info;
});

const logger = createLogger({
  format: format.combine(
    ignorePrivate(),
    format.json()
  ),
  transports: [new transports.Console()]
});

// Outputs: {"level":"error","message":"Public error to share"}
logger.log({
  level: 'error',
  message: 'Public error to share'
});

// Messages with { private: true } will not be written when logged.
logger.log({
  private: true,
  level: 'error',
  message: 'This is super secret - hide it.'
});

Use of format.combine will respect any falsey values return and stop evaluation of later formats in the series. For example:

const { format } = require('winston');
const { combine, timestamp, label } = format;

const willNeverThrow = format.combine(
  format(info => { return false })(), // Ignores everything
  format(info => { throw new Error('Never reached') })()
);

Creating custom formats

Formats are prototypal objects (i.e. class instances) that define a single method: transform(info, opts) and return the mutated info:

  • info: an object representing the log message.
  • opts: setting specific to the current instance of the format.

They are expected to return one of two things:

  • An info Object representing the modified info argument. Object references need not be preserved if immutability is preferred. All current built-in formats consider info mutable, but [immutablejs] is being considered for future releases.
  • A falsey value indicating that the info argument should be ignored by the caller. (See: Filtering info Objects) below.

winston.format is designed to be as simple as possible. To define a new format, simply pass it a transform(info, opts) function to get a new Format.

The named Format returned can be used to create as many copies of the given Format as desired:

const { format } = require('winston');

const volume = format((info, opts) => {
  if (opts.yell) {
    info.message = info.message.toUpperCase();
  } else if (opts.whisper) {
    info.message = info.message.toLowerCase();
  }

  return info;
});

// `volume` is now a function that returns instances of the format.
const scream = volume({ yell: true });
console.dir(scream.transform({
  level: 'info',
  message: `sorry for making you YELL in your head!`
}, scream.options));
// {
//   level: 'info'
//   message: 'SORRY FOR MAKING YOU YELL IN YOUR HEAD!'
// }

// `volume` can be used multiple times to create different formats.
const whisper = volume({ whisper: true });
console.dir(whisper.transform({
  level: 'info',
  message: `WHY ARE THEY MAKING US YELL SO MUCH!`
}, whisper.options));
// {
//   level: 'info'
//   message: 'why are they making us yell so much!'
// }

Logging Levels

Logging levels in winston conform to the severity ordering specified by RFC5424: severity of all levels is assumed to be numerically ascending from most important to least important.

Each level is given a specific integer priority. The higher the priority the more important the message is considered to be, and the lower the corresponding integer priority. For example, as specified exactly in RFC5424 the syslog levels are prioritized from 0 to 7 (highest to lowest).

{
  emerg: 0,
  alert: 1,
  crit: 2,
  error: 3,
  warning: 4,
  notice: 5,
  info: 6,
  debug: 7
}

Similarly, npm logging levels are prioritized from 0 to 6 (highest to lowest):

{
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  verbose: 4,
  debug: 5,
  silly: 6
}

If you do not explicitly define the levels that winston should use, the npm levels above will be used.

Using Logging Levels

Setting the level for your logging message can be accomplished in one of two ways. You can pass a string representing the logging level to the log() method or use the level specified methods defined on every winston Logger.

//
// Any logger instance
//
logger.log('silly', "127.0.0.1 - there's no place like home");
logger.log('debug', "127.0.0.1 - there's no place like home");
logger.log('verbose', "127.0.0.1 - there's no place like home");
logger.log('info', "127.0.0.1 - there's no place like home");
logger.log('warn', "127.0.0.1 - there's no place like home");
logger.log('error', "127.0.0.1 - there's no place like home");
logger.info("127.0.0.1 - there's no place like home");
logger.warn("127.0.0.1 - there's no place like home");
logger.error("127.0.0.1 - there's no place like home");

//
// Default logger
//
winston.log('info', "127.0.0.1 - there's no place like home");
winston.info("127.0.0.1 - there's no place like home");

winston allows you to define a level property on each transport which specifies the maximum level of messages that a transport should log. For example, using the syslog levels you could log only error messages to the console and everything info and below to a file (which includes error messages):

const logger = winston.createLogger({
  levels: winston.config.syslog.levels,
  transports: [
    new winston.transports.Console({ level: 'error' }),
    new winston.transports.File({
      filename: 'combined.log',
      level: 'info'
    })
  ]
});

You may also dynamically change the log level of a transport:

const transports = {
  console: new winston.transports.Console({ level: 'warn' }),
  file: new winston.transports.File({ filename: 'combined.log', level: 'error' })
};

const logger = winston.createLogger({
  transports: [
    transports.console,
    transports.file
  ]
});

logger.info('Will not be logged in either transport!');
transports.console.level = 'info';
transports.file.level = 'info';
logger.info('Will be logged in both transports!');

winston supports customizable logging levels, defaulting to npm style logging levels. Levels must be specified at the time of creating your logger.

Using Custom Logging Levels

In addition to the predefined npm, syslog, and cli levels available in winston, you can also choose to define your own:

const myCustomLevels = {
  levels: {
    foo: 0,
    bar: 1,
    baz: 2,
    foobar: 3
  },
  colors: {
    foo: 'blue',
    bar: 'green',
    baz: 'yellow',
    foobar: 'red'
  }
};

const customLevelLogger = winston.createLogger({
  levels: myCustomLevels.levels
});

customLevelLogger.foobar('some foobar level-ed message');

Although there is slight repetition in this data structure, it enables simple encapsulation if you do not want to have colors. If you do wish to have colors, in addition to passing the levels to the Logger itself, you must make winston aware of them:

winston.addColors(myCustomLevels.colors);

This enables loggers using the colorize formatter to appropriately color and style the output of custom levels.

Additionally, you can also change background color and font style. For example,

baz: 'italic yellow',
foobar: 'bold red cyanBG'

Possible options are below.

  • Font styles: bold, dim, italic, underline, inverse, hidden, strikethrough.

  • Font foreground colors: black, red, green, yellow, blue, magenta, cyan, white, gray, grey.

  • Background colors: blackBG, redBG, greenBG, yellowBG, blueBG magentaBG, cyanBG, whiteBG

Colorizing Standard logging levels

To colorize the standard logging level add

winston.format.combine(
  winston.format.colorize(),
  winston.format.simple()
);

where winston.format.simple() is whatever other formatter you want to use. The colorize formatter must come before any formatters adding text you wish to color.

Colorizing full log line when json formatting logs

To colorize the full log line with the json formatter you can apply the following

winston.format.combine(
  winston.format.json(),
  winston.format.colorize({ all })
);

Transports

There are several core transports included in winston, which leverage the built-in networking and file I/O offered by Node.js core. In addition, there are additional transports written by members of the community.

Multiple transports of the same type

It is possible to use multiple transports of the same type e.g. winston.transports.File when you construct the transport.

const logger = winston.createLogger({
  transports: [
    new winston.transports.File({
      filename: 'combined.log',
      level: 'info'
    }),
    new winston.transports.File({
      filename: 'errors.log',
      level: 'error'
    })
  ]
});

If you later want to remove one of these transports you can do so by using the transport itself. e.g.:

const combinedLogs = logger.transports.find(transport => {
  return transport.filename === 'combined.log'
});

logger.remove(combinedLogs);

Adding Custom Transports

Adding a custom transport is easy. All you need to do is accept any options you need, implement a log() method, and consume it with winston.

const Transport = require('winston-transport');
const util = require('util');

//
// Inherit from `winston-transport` so you can take advantage
// of the base functionality and `.exceptions.handle()`.
//
module.exports = class YourCustomTransport extends Transport {
  constructor(opts) {
    super(opts);
    //
    // Consume any custom options here. e.g.:
    // - Connection information for databases
    // - Authentication information for APIs (e.g. loggly, papertrail,
    //   logentries, etc.).
    //
  }

  log(info, callback) {
    setImmediate(() => {
      this.emit('logged', info);
    });

    // Perform the writing to the remote service
    callback();
  }
};

Common Transport options

As every transport inherits from winston-transport, it's possible to set a custom format and a custom log level on each transport separately:

const logger = winston.createLogger({
  transports: [
    new winston.transports.File({
      filename: 'error.log',
      level: 'error',
      format: winston.format.json()
    }),
    new winston.transports.Http({
      level: 'warn',
      format: winston.format.json()
    }),
    new winston.transports.Console({
      level: 'info',
      format: winston.format.combine(
        winston.format.colorize(),
        winston.format.simple()
      )
    })
  ]
});

Exceptions

Handling Uncaught Exceptions with winston

With winston, it is possible to catch and log uncaughtException events from your process. With your own logger instance you can enable this behavior when it's created or later on in your applications lifecycle:

const { createLogger, transports } = require('winston');

// Enable exception handling when you create your logger.
const logger = createLogger({
  transports: [
    new transports.File({ filename: 'combined.log' })
  ],
  exceptionHandlers: [
    new transports.File({ filename: 'exceptions.log' })
  ]
});

// Or enable it later on by adding a transport or using `.exceptions.handle`
const logger = createLogger({
  transports: [
    new transports.File({ filename: 'combined.log' })
  ]
});

// Call exceptions.handle with a transport to handle exceptions
logger.exceptions.handle(
  new transports.File({ filename: 'exceptions.log' })
);

If you want to use this feature with the default logger, simply call .exceptions.handle() with a transport instance.

//
// You can add a separate exception logger by passing it to `.exceptions.handle`
//
winston.exceptions.handle(
  new winston.transports.File({ filename: 'path/to/exceptions.log' })
);

//
// Alternatively you can set `handleExceptions` to true when adding transports
// to winston.
//
winston.add(new winston.transports.File({
  filename: 'path/to/combined.log',
  handleExceptions: true
}));

To Exit or Not to Exit

By default, winston will exit after logging an uncaughtException. If this is not the behavior you want, set exitOnError = false

const logger = winston.createLogger({ exitOnError: false });

//
// or, like this:
//
logger.exitOnError = false;

When working with custom logger instances, you can pass in separate transports to the exceptionHandlers property or set handleExceptions on any transport.

Example 1
const logger = winston.createLogger({
  transports: [
    new winston.transports.File({ filename: 'path/to/combined.log' })
  ],
  exceptionHandlers: [
    new winston.transports.File({ filename: 'path/to/exceptions.log' })
  ]
});
Example 2
const logger = winston.createLogger({
  transports: [
    new winston.transports.Console({
      handleExceptions: true
    })
  ],
  exitOnError: false
});

The exitOnError option can also be a function to prevent exit on only certain types of errors:

function ignoreEpipe(err) {
  return err.code !== 'EPIPE';
}

const logger = winston.createLogger({ exitOnError: ignoreEpipe });

//
// or, like this:
//
logger.exitOnError = ignoreEpipe;

Rejections

Handling Uncaught Promise Rejections with winston

With winston, it is possible to catch and log unhandledRejection events from your process. With your own logger instance you can enable this behavior when it's created or later on in your applications lifecycle:

const { createLogger, transports } = require('winston');

// Enable rejection handling when you create your logger.
const logger = createLogger({
  transports: [
    new transports.File({ filename: 'combined.log' })
  ],
  rejectionHandlers: [
    new transports.File({ filename: 'rejections.log' })
  ]
});

// Or enable it later on by adding a transport or using `.rejections.handle`
const logger = createLogger({
  transports: [
    new transports.File({ filename: 'combined.log' })
  ]
});

// Call rejections.handle with a transport to handle rejections
logger.rejections.handle(
  new transports.File({ filename: 'rejections.log' })
);

If you want to use this feature with the default logger, simply call .rejections.handle() with a transport instance.

//
// You can add a separate rejection logger by passing it to `.rejections.handle`
//
winston.rejections.handle(
  new winston.transports.File({ filename: 'path/to/rejections.log' })
);

//
// Alternatively you can set `handleRejections` to true when adding transports
// to winston.
//
winston.add(new winston.transports.File({
  filename: 'path/to/combined.log',
  handleRejections: true
}));

Profiling

In addition to logging messages and metadata, winston also has a simple profiling mechanism implemented for any logger:

//
// Start profile of 'test'
//
logger.profile('test');

setTimeout(function () {
  //
  // Stop profile of 'test'. Logging will now take place:
  //   '17 Jan 21:00:00 - info: test duration=1000ms'
  //
  logger.profile('test');
}, 1000);

Also you can start a timer and keep a reference that you can call .done() on:

 // Returns an object corresponding to a specific timing. When done
 // is called the timer will finish and log the duration. e.g.:
 //
 const profiler = logger.startTimer();
 setTimeout(function () {
   profiler.done({ message: 'Logging message' });
 }, 1000);

All profile messages are set to 'info' level by default, and both message and metadata are optional. For individual profile messages, you can override the default log level by supplying a metadata object with a level property:

logger.profile('test', { level: 'debug' });

Querying Logs

winston supports querying of logs with Loggly-like options. See Loggly Search API. Specifically: File, Couchdb, Redis, Loggly, Nssocket, and Http.

const options = {
  from: new Date() - (24 * 60 * 60 * 1000),
  until: new Date(),
  limit: 10,
  start: 0,
  order: 'desc',
  fields: ['message']
};

//
// Find items logged between today and yesterday.
//
logger.query(options, function (err, results) {
  if (err) {
    /* TODO: handle me */
    throw err;
  }

  console.log(results);
});

Streaming Logs

Streaming allows you to stream your logs back from your chosen transport.

//
// Start at the end.
//
winston.stream({ start: -1 }).on('log', function(log) {
  console.log(log);
});

Further Reading

Using the Default Logger

The default logger is accessible through the winston module directly. Any method that you could call on an instance of a logger is available on the default logger:

const winston = require('winston');

winston.log('info', 'Hello distributed log files!');
winston.info('Hello again distributed logs');

winston.level = 'debug';
winston.log('debug', 'Now my debug messages are written to console!');

By default, no transports are set on the default logger. You must add or remove transports via the add() and remove() methods:

const files = new winston.transports.File({ filename: 'combined.log' });
const console = new winston.transports.Console();

winston.add(console);
winston.add(files);
winston.remove(console);

Or do it with one call to configure():

winston.configure({
  transports: [
    new winston.transports.File({ filename: 'somefile.log' })
  ]
});

For more documentation about working with each individual transport supported by winston see the winston Transports document.

Awaiting logs to be written in winston

Often it is useful to wait for your logs to be written before exiting the process. Each instance of winston.Logger is also a [Node.js stream]. A finish event will be raised when all logs have flushed to all transports after the stream has been ended.

const transport = new winston.transports.Console();
const logger = winston.createLogger({
  transports: [transport]
});

logger.on('finish', function (info) {
  // All `info` log messages has now been logged
});

logger.info('CHILL WINSTON!', { seriously: true });
logger.end();

It is also worth mentioning that the logger also emits an 'error' event if an error occurs within the logger itself which you should handle or suppress if you don't want unhandled exceptions:

//
// Handle errors originating in the logger itself
//
logger.on('error', function (err) { /* Do Something */ });

Working with multiple Loggers in winston

Often in larger, more complex, applications it is necessary to have multiple logger instances with different settings. Each logger is responsible for a different feature area (or category). This is exposed in winston in two ways: through winston.loggers and instances of winston.Container. In fact, winston.loggers is just a predefined instance of winston.Container:

const winston = require('winston');
const { format } = winston;
const { combine, label, json } = format;

//
// Configure the logger for `category1`
//
winston.loggers.add('category1', {
  format: combine(
    label({ label: 'category one' }),
    json()
  ),
  transports: [
    new winston.transports.Console({ level: 'silly' }),
    new winston.transports.File({ filename: 'somefile.log' })
  ]
});

//
// Configure the logger for `category2`
//
winston.loggers.add('category2', {
  format: combine(
    label({ label: 'category two' }),
    json()
  ),
  transports: [
    new winston.transports.Http({ host: 'localhost', port:8080 })
  ]
});

Now that your loggers are setup, you can require winston in any file in your application and access these pre-configured loggers:

const winston = require('winston');

//
// Grab your preconfigured loggers
//
const category1 = winston.loggers.get('category1');
const category2 = winston.loggers.get('category2');

category1.info('logging to file and console transports');
category2.info('logging to http transport');

If you prefer to manage the Container yourself, you can simply instantiate one:

const winston = require('winston');
const { format } = winston;
const { combine, label, json } = format;

const container = new winston.Container();

container.add('category1', {
  format: combine(
    label({ label: 'category one' }),
    json()
  ),
  transports: [
    new winston.transports.Console({ level: 'silly' }),
    new winston.transports.File({ filename: 'somefile.log' })
  ]
});

const category1 = container.get('category1');
category1.info('logging to file and console transports');

Installation

npm install winston
yarn add winston

Run Tests

All of the winston tests are written with mocha, nyc, and assume. They can be run with npm.

npm test

winston's People

Contributors

3rd-eden avatar acrazing avatar chjj avatar chrisalderson avatar coderarity avatar compulim avatar dabh avatar dependabot[bot] avatar fb55 avatar fearphage avatar fotoverite avatar harriha avatar indexzero avatar jcrugzz avatar jfhbrook avatar josh-shaw-dev avatar kibertoad avatar lisa-lionheart avatar marak avatar maverick1872 avatar mmalecki avatar nimrod-becker avatar pksunkara avatar pose avatar pulkit0729 avatar rictorres avatar samzilverberg avatar serayaeryn avatar ubun2 avatar wbt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

winston's Issues

ability to pass the 'stringify' option to common.log

file.js, L92-99

File.prototype.log = function (level, msg, meta, callback) {
  if (this.silent) {
    return callback(null, true);
  }

  var self = this, output = common.log({
    level:     level,
    message:   msg,
    meta:      meta,
    json:      this.json,
    colorize:  this.colorize,
    timestamp: this.timestamp
  }) + '\n';

common.js, L102-120

exports.log = function (options) {
  var timestampFn = typeof options.timestamp === 'function' ? options.timestamp : exports.timestamp,
      timestamp   = options.timestamp ? timestampFn() : null,
      meta        = options.meta ? exports.clone(options.meta) : null,
      output;

  if (options.json) {
    output         = meta || {};
    output.level   = options.level;
    output.message = options.message;

    if (timestamp) {
      output.timestamp = timestamp;
    }

    return typeof options.stringify === 'function' 
      ? options.stringify(output)
      : JSON.stringify(output);
  }

common.log() expects -among others- the 'stringify' option to be a function to be called when outputting the log msg.

Since common.log() is called with fixed options from within file.js (or console.js), that 'stringify' feature can not be used, and instead the log format is always JSON.stringify({level:'info', msg: 'log message'})

Since common.log already have that option, it could be passed to it through the options passed along when adding the transport.

Issue with console output recognizing user-created levels

When using a personalized levels for a logger, any console-based transport outputs something similar to the following

undefined: Foo level-ed message.

Whereas the file/stream-based transport outputs something similar to the following

{"level":"foo","message":"Foo level-ed message"}

-Brenzenb

Formatting difference between console and file...

Hi

How my custom logger is defined:

var customLevels = {
levels: {
trace: 0,
debug: 1,
info: 2,
warn: 3,
error: 4,
fatal: 5
},
colors: {
trace: "blue",
debug: "grey",
info: "white",
warn: "magenta",
error: "red",
fatal: "red"
}
};
winston.addColors(customLevels.colors);

var logger = new (winston.Logger)({
levels: customLevels.levels,
exitOnError: false,
transports: [
new winston.transports.Console({
level: "debug",
silent: false,
colorize: true,
timestamp: true }),

             new winston.transports.File({ 
                 level: "debug", 
                 silent: false, 
                 colorize: true, 
                 timestamp: true,
                 filename: "../logs/generic.log",
                 maxsize: 5000,
                 maxFiles: 5 })
            ],
exceptionHandlers: [
             new winston.transports.File({
                 level: "debug", 
                 silent: false, 
                 colorize: true, 
                 timestamp: true,
                 filename: "../logs/error.log",
                 maxSize: 5000,
                 maxFiles: 3})
            ]

});

Logging the following:
logger.debug("Received [" + util.inspect(msg, true, null) + "].");

shows (in console)
14 Dec 11:04:45 - debug: Received [{ _queryId: 1, _workerId: 1, cmd: 'online' }].

shows (in generic.log)
{"level":"debug","message":"Received [{ _queryId: 1, _workerId: 1, cmd: 'online' }].","timestamp":"14 Dec 11:04:45"}

I don't understand the different format of the entry. I was expecting to see the same entry in both console and file.
Is that meant to be like that?

How to use colors?

Winston seems perfect, but I just can't seem to figure this out...

How do I use colors with winston? Can I make particular messages have different colors? Help please :-)

How to handle uncaught exceptions

I want to log the uncaught exceptions with Winston and exit process. I've configured logger like this

var winston = require('winston');
var logger = new (winston.Logger)({
    transports: [
      new winston.transports.File({ filename: './all-logs.log', timestamp: true, maxsize: 1000000 })
    ],
    exceptionHandlers: [
      new winston.transports.File({ filename: './exceptions.log', timestamp: true, maxsize: 1000000 })
    ],  
    exitOnError: true,
});

Then try throw one error, but no exceptions.logs file was created
throw new Exception("Error here ...");

Did I have the right configuration?

Undocumented timestamp option for console logger

To use timestamps in the console log I need to do the following:

winston = require('winston');
winston.remove(winston.transports.Console);
winston.add(winston.transports.Console, {timestamp: true});

Also, there is no mention of the timestamp option in the docs for ConsoleLogger in the Readme.

Can we have timestamps enabled in Console logging by default? Happy to provide a pull request for this if necessary?

Question: Is this safe use of Winston?

Given winston is async will the final winston.info 'Exiting' guarantee to run if output is to do file/loggly etc..?

winston = require 'winston'

process.on 'uncaughtException', (er) ->
  winston.error 'Crashed', er
  process.exit 1 

process.on 'exit', ->
  winston.info 'Exiting'

winston.info 'Starting server'

app = (require 'express').createServer()

app.get '/', (req, res) -> 
  throw new Error 'aa'
  res.send 'hello world'

app.listen 3000

A logger with console transport that does not print out debug messages

How can I configure a logger instance with a console transport so that it does not print out debug messages?

var log = new (winston.Logger) ({
    level: 'info',
    transports: [
        new (winston.transports.Console)({
            colorize: true,
            level: 'info',
            timestamp: true,
            handleExceptions: true,
        }),
    ],
});

This is what I have been trying, but with no success.

padLevels not working correctly

for "padLevels" to work logger.js (around line 128) has to be changed from:

// If we should pad for levels, do so
  if (this.padLevels) {
    msg = new Array(this.levelLength - level.length).join(' ') + msg;
  }

to

// If we should pad for levels, do so
  if (this.padLevels) {
    msg = new Array(this.levelLength - level.length + 1).join(' ') + msg;
  }

because Array(n).join(" ") produces only (n-1) spaces.

broken on >node0.5

node.js:195
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: require.paths is removed. Use node_modules folders, or the NODE_PATH environment variable instead.
at Function. (module.js:360:11)
at Object. (/usr/local/lib/node_modules/forever/node_modules/winston/lib/winston.js:9:8)
at Module._compile (module.js:420:26)
at Object..js (module.js:459:10)
at Module.load (module.js:335:31)
at Function._load (module.js:294:12)
at Module.require (module.js:341:17)
at require (module.js:352:17)
at Object. (/usr/local/lib/node_modules/forever/bin/forever:5:15)
at Module._compile (module.js:420:26)

loggly config file inconsistency between winston and node-loggly

This may just be a documentation issue, or perhaps it makes sense to fix:

The format for the config file in node-loggly

{
"subdomain": "your-subdomain",
"auth": {
"username": "your-username",
"password": "your-password"
},
"inputs": [{
"token": "your-really-long-token-you-got-when-you-created-an-http-input",
"id": 000 // ID of this input
}]
}

The format for loggly config in winston:

{
"transports": {
"loggly": {
"subdomain": "your-subdomain",
"inputToken": "really-long-token-you-got-from-loggly",
"auth": {
"username": "your-username",
"password": "your-password"
}
}
}
}

Why not modify winston to use the node-loggly config file format?

Request for comment on winston API for search and analysis of logs

I've been working on a part of what might go into an API for searching and analyzing logs via winston:
Real-time counters for tracking log volume across whatever properties you include in the meta parameter and at whatever time resolution you want. An example of this is included below.

**I'm looking for help

  1. in planning out how this API might look in general
  2. Any feedback on the counter concept specifically.**

API questions

The main question is what needs to go into a search/analytics API for winston logs?

  • indexzero suggested find() and search() methods:
    search() seems straightforward: search for logs matching a keyword expresssion
    find() is more open-ended, what makes most sense for me is something like MongoDB's find() function that would allow parameterized queries across the properties in the meta argument value

It seems practical to build search() in a way that's transport independent - though I'm not all that familiar with tools for doing this (e.g. Lucene ?)

API Concerns

My concern with find() is that the syntax for a search expression would depend a lot on the transport - addressing this problem would involve using a small subset of capabilities or writing a generalized query language.

My concern in general is about the demand for transport-independent log analysis and search vs. using transport-specific capabilities to do each of these things. Anyone seen evidence of this demand?

Example of my counter concept

This log statement

logger.log("My log message", {referer:'google.com',location:'Boston, MA'});

results in the following inserts to a database (currently only redis is supported):

var redis_client = require('redis').redis.createClient();
redis_client.incr("referer::google.com||2011-05-31-8-52"); // counting at minute level
redis_client.incr("location::Boston, MA||2011-05-31-8-52"); // counting at minute level

string passed as meta is not recorded in Loggly via JSON transport

When I use winston.error('my error', 'some string');, with Loggly transport configured with JSON input, only 'some string' is recorded in Loggly logs, without the 'my error' string.

I know this is probably because 'some string' is not a JSON / Javascript object, but I would be cool if it got automatically turned into a simple one, e.g. { meta: 'some string' }, so that Loggly accepts it.

The Console transport prints these as a single string though: 'my error some string'.

Make it possible to serialize log metadata with JSON.stringify (for non-JSON inputs)

Please make it configurable to serialize log metadata with JSON.stringify (for non-JSON inputs).

Currently the same can be achieved by overriding require('winston/lib/winston/common').serialize = JSON.stringify; - but of course that's a hack.

The current serialization algorithm (key=val, ...) for Loggly (but applies also to Console, etc.), may not be the best one for more complex objects, where JSON.stringify will do just fine.

The current serialization algorithm also produces ', , , , ,' output when serializing an object which contains multiple empty sub-objects.

unable to log nested objects as metadata

I'm not really sure if this is even supposed to be possible but everytime I try to log an object with several layers of nesting it crashes node yet I can util.inspect it just fine.

Here's the object I'm trying to log:

{ project: { basedir: '/home/jon/gits/JxLib', default: 'deploy' },
  app: 
   { name: 'jxlib',
     path: '/jxlib',
     version: '3.0',
     home: '/home/jon/gits/JxLib',
     build: '/home/jon/gits/JxLib/build',
     dist: '/home/jon/gits/JxLib/dist',
     deploy: '/home/jon/gits/JxLib/www',
     docs: '/home/jon/gits/JxLib/www/reference',
     vendor: '/home/jon/gits/JxLib/vendor',
     utils: '/home/jon/gits/JxLib/utils' },
  dependencies: { NaturalDocs: '/home/jon/gits/JxLib/utilsNaturalDocs-1.4/NaturalDocs' },
  loader: 
   { base: { moveImages: false, rewriteImageUrl: false },
     repos: 
      { core: { paths: { js: '/home/jon/gits/JxLib/vendor/mootools-core/Source' } },
        more: { paths: { js: '/home/jon/gits/JxLib/vendor/mootools-more/Source' } },
        jxlib: 
         { paths: 
            { js: '/home/jon/gits/JxLib/build/Source',
              css: '/home/jon/gits/JxLib/build/themes/{theme}/css',
              cssalt: '/home/jon/gits/JxLib/build/themes/{theme}' } } } },
  tasks: [],
  filepath: '/home/jon/gits/JxLib/builder/config.js',
  targets: '/home/jon/gits/JxLib/builder/targets' }

I'm passing it to a logger instance using something like:

logger.debug("log message", obj);

where obj is the one noted above.

is this correct behaviour or is it actually a bug somewhere?

Thanks,
Jon Bomgardner

Custom Timestamp format

I will see if I can't do this myself and submit the pull request, but someone more capable may be able to do it swiftly.

The point is to be able to set, per Transport, a timestamp function which takes the options and returns the timestamp.

For example, I like my text logs to show unixtime, then human readable but I couldn't find a way to get Winston to change the timestamp function at runtime, so I had to hack it into the source (not ideal!).

I feel this could be added as an option but have not got my head around the way this module fits everything together to allow this to happen.

winston doesn't support stable nodejs (version < 0.3)

$ npm install winston
npm info it worked if it ends with ok
npm info using [email protected]
npm info using [email protected]
npm WARN Not supported on [email protected] winston
npm info fetch http://registry.npmjs.org/winston/-/winston-0.1.3.tgz
npm info calculating sha1 /tmp/npm-1296136112394/1296136113189-0.6086350905243307/tmp.tgz
npm info shasum 9bdf01f3b145dd72dc10a122c4ffd1031d686739
npm info calculating sha1 /home/ashamrin/local/lib/node/.npm/.cache/winston/0.1.3/package.tgz
npm info shasum 980a9b32d718a2e33ed8154a4db79d2b49924a9f
npm ERR! [email protected] not compatible with your version of node
npm ERR! Requires: node@>= 0.3.0
npm ERR! You have: [email protected]
npm not ok

error output obscures the error

error: uncaughtException pid=18175, uid=0, gid=0, cwd=/home/dominic/clean/nodejitsu, execPath=/usr/local/bin/node, version=v0.4.10, argv=[node, /home/dominic/clean/nodejitsu/bin/balancer, -e, production, --domain, nodejitsu], rss=26300416, vsize=64045056, heapTotal=25608832, heapUsed=13392388, loadavg=[0.37451171875, 0.197265625, 0.17529296875], uptime=19433, trace=[column=3, file=/home/dominic/clean/nodejitsu/lib/nodejitsu/balancer/index.js, function=Object.createServer, line=62, method=createServer, native=false, column=29, file=/home/dominic/clean/nodejitsu/lib/nodejitsu/balancer/index.js, function=null, line=72, method=null, native=false, column=7, file=/home/dominic/clean/nodejitsu/lib/nodejitsu.js, function=null, line=76, method=null, native=false, column=5, file=/home/dominic/clean/nodejitsu/node_modules/haibu/lib/haibu/utils/index.js, function=null, line=382, method=null, native=false, column=25, file=/home/dominic/clean/nodejitsu/node_modules/async/lib/async.js, function=null, line=126, method=null, native=false, column=7, file=/home/dominic/clean/nodejitsu/node_modules/haibu/lib/haibu/utils/index.js, function=null, line=377, method=null, native=false, column=21, file=/home/dominic/clean/nodejitsu/node_modules/mkdirp/index.js, function=null, line=10, method=null, native=false, column=19, file=path.js, function=null, line=292, method=null, native=false], stack=[ReferenceError: server is not defined,     at Object.createServer (/home/dominic/clean/nodejitsu/lib/nodejitsu/balancer/index.js:62:3),     at /home/dominic/clean/nodejitsu/lib/nodejitsu/balancer/index.js:72:29,     at /home/dominic/clean/nodejitsu/lib/nodejitsu.js:76:7,     at /home/dominic/clean/nodejitsu/node_modules/haibu/lib/haibu/utils/index.js:382:5,     at /home/dominic/clean/nodejitsu/node_modules/async/lib/async.js:126:25,     at /home/dominic/clean/nodejitsu/node_modules/haibu/lib/haibu/utils/index.js:377:7,     at /home/dominic/clean/nodejitsu/node_modules/mkdirp/index.js:10:21,     at path.js:292:19]

not very helpful.

Question: Loggly timeoute

If you have a callback waiting on a log action and a transport such as Loggly, what is the default timeout? Can this be configured so if Loggly is in a bad state (such as accepting the socket but hanging etc..) we dont wait for maximum/default socket timeout or one of those scenarios where the timeout doesnt get invoked (drip feeding a packet a minute etc..) we arent vunerable. Lets say we have this:

function handleUncaughtException(err) {
log.error('CRAP. in an unreliable state, lets get out of here QUICK and let supervisord,upstart, monit, god etc.. restart us')
log.info('exiting', function() {
   process.exit(0)
})
}

Error in doc

At the require at chapter "MongoDB Transport" :
var MongoDB = require('winston-mongoDB').MongoDB;

It is winston-mongodb and not winston-mongoDB

file transport needs a way to cap total log size

Currently, the file transport in Winston has a maximum file size, but instead of implementing a rolling buffer, Winston simply creates new files. This is good if you want to implement a log rotation system, but in many cases you are only interested in recent log output or are using a different transport for long-term log storage.

We think this can be implemented without too much difficulty by adding an option called maxFiles, which would limit the number of new files Winston creates. If the amount of created files grows too large, Winston should start deleting old logs.

You can find the transport module here: https://github.com/flatiron/winston/blob/master/lib/winston/transports/file.js.

Transport constructor should accept undefined "level" instead of defaulting to "info"

By default, we have no way to control the level of all transports of a logger through the logger's "level" property, because in transport.js, the Transport constructor defaults its "level" property to "info", causing the transport's level always to be used instead of logger's level.

This logic is implemented in the log function in logger.js as this:

  for (var i = 0, l = this._names.length; i < l; i++) {
    var transport = this.transports[this._names[i]];
    if ((transport.level && self.levels[transport.level] <= self.levels[level])
      || (!transport.level && self.levels[self.level] <= self.levels[level])) {
      transport.log(level, msg, meta, function (err) {
        self.emit('logging', transport, level, msg, meta);
      });
    }
  }

and in transport.js:

var Transport = exports.Transport = function (options) {
  events.EventEmitter.call(this);

  options               = options        || {};  
  this.level            = options.level  || 'info';
  this.silent           = options.silent || false;
  this.handleExceptions = options.handleExceptions || false;
};

So I think it's better to leave transport's level to undefined in its constructor rather than defaulting it to 'info'.

handleException doesn't work in coffee-script

Hi guys,

The code below doesn't work if you run it in coffee-script. The reason is probably because coffee-script compiler listen for exceptions as well.

winston = require 'winston'
path = require 'path'

winston.handleExceptions new winston.transports.File
  filename: path.join __dirname, 'exceptions.log'

# this throws an exception
test = require 'non-existent-module'

run it in console:

$ coffee test-coffee.coffee

the output is:

Error: Cannot find module 'non-existent-module'
    at Function._resolveFilename (module.js:326:11)
    at Function._load (module.js:271:25)
    at require (module.js:355:19)
    at Object.<anonymous> (test-coffee.coffee:8:10)
    at Object.<anonymous> (test-coffee.coffee:9:4)
    at Module._compile (module.js:411:26)
    at Object.run (/usr/local/lib/node_modules/coffee-script/lib/coffee-script.js:57:25)
    at /usr/local/lib/node_modules/coffee-script/lib/command.js:147:29
    at /usr/local/lib/node_modules/coffee-script/lib/command.js:115:26
    at [object Object].<anonymous> (fs.js:107:5)

but if you run

$ coffee -c test-coffee.coffee
$ node test-coffee.js

then everything works flawlessly

Add ability for File transport to split up logs by date

@indexzero -

How would you feel about adding an optional API parameter to the File transport so that it can split up log files by date? The idea would be that on each new day, a new log file would be created and Winston would automatically handle all of this / know which log file to write to based on the date.

log file gets overwritten by default

It's confusing to have to specify { ... options: {flags: 'a'}} when adding File transport. I think append mode should be on by default (lib/winston/transports/file.js):

    if (options.filename) this.stream = fs.createWriteStream(options.filename, options.options || {flags: 'a'});

cli mode

Reading the doc I was expecting to get a formatting output for the following code

var winston = require('winston');

winston.cli();

winston.debug("format me", {
  colors: '0.x.x',
  eyes: '0.1.x',
  findit: '0.0.x',
  npm: '1.0.x',
  optimist: '0.2.x',
  semver: '1.0.x',
  winston: '0.2.x'
});

instead I get an inline output
debug: format me colors=0.x.x, eyes=0.1.x, findit=0.0.x, npm=1.0.x, optimist=0.2.x, semver=1.0.x, winston=0.2.x

Can you let me know what's wrong about it ?

Problem with riak-js dependency: Cannot find module './lib/index'

Not really a problem with winston itself but worth mentioning. I did a npm install winston and it successfully pulled down winston along with riak and the other dependencies. When I first tried running the app I received...

Error: Cannot find module './lib/index'
at Function._resolveFilename (module.js:320:11)
at Function._load (module.js:266:25)
at require (module.js:348:19)
at Object.<anonymous> (/Users/dpadbury/dev/projects/.../node_modules/winston/node_modules/riak-js/index.js:1:80)

Dropping into the riak-js directory and running "cake build" created the lib directory and from then on all was fine.

Weird number print bug

Try this:

var winston = require('winston');

debug('some number %i', '639185824293104868');

function debug() {
    winston.info.apply(this, arguments);
}

This is the output:

info: some number: %i 0=1, 1=8, 2=8, 3=7, 4=5, 5=9, 6=9, 7=5, 8=5, 9=6, 10=5, 11=0, 12=8, 13=8, 14=2, 15=0, 16=6, 17=2, 18=6, bold=1887599556508820626, underline=1887599556508820626, italic=1887599556508820626, inverse=1887599556508820626, grey=1887599556508820626, yellow=1887599556508820626, red=1887599556508820626, green=1887599556508820626, blue=1887599556508820626, white=1887599556508820626, cyan=1887599556508820626, magenta=1887599556508820626, rainbow=1887599556508820626, zalgo=1ͭ̄͐̈̔́ͫͧ̉͊8̓̆̋̍͌͐̓̅̾̚8̈͆̒̆̏ͯ̿ͨ͛͠7̐́͑ͨͥ͛̇ͩ͂̆5͐̈̍ͥͯ̊ͮ͌ͤͩ9̹̣̎ͯ͊͋̀ͪ̃͡9̧͕̼̰̼̈̎͐̏̚5ͥ̒ͬ̎̿̽͑ͤ̾ͥ5ͦ́͌ͤͧͩ̽ͤͤ̏6̀̃̃͋ͪ̍ͣ͑͛ͣ5ͧͦ̈̈̎̎̾̎̊́ ҉͖͉̹̩̰̫͓̬̜0ͩ͊̉̒ͫ̃͊̍ͬ̉8̛̝̣̱͌̇ͣ͗̏̈8͗͋̽̔͋̓̀͌ͫ͆2̈̌̾̾̒̅ͮ̚ ҉͉̠̫̦̱͓̰̺͓0̴̙͗͛ͯͦ͂ͮ̈̎6̪̺͗ͨ͑͆̎͛̂͢2̵͓̥̘̯̒ͤ̒̋ͭ6ͬ̓ͭ̆͛ͭ̾̉̊̚

Version 0.3.5 transports are not compatible with 0.4

Here is the error.

error: TypeError: Object [object Object] has no method 'on'
at [object Object].add (/Users/subrah/dev/projects/ebay/ql.io/site/console/node_modules/winston/lib/winston/logger.js:263:12)
at Object.add (/Users/subrah/dev/projects/ebay/ql.io/site/console/node_modules/winston/lib/winston.js:59:34)

Ability to pass in multiple arguments to logging calls?

@pigmej ran into an issue today in the IRC

 var winston = require('winston');
 winston.log('info', 'Hello distributed log files!', {"foo":"bar"}, ['123', '456']);


  node.js:134
          throw e; // process.nextTick error, or 'error' event on first tick
          ^
  TypeError: object is not a function
      at Array.CALL_NON_FUNCTION (native)
      at /usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston/logger.js:107:42
      at [object Object].log (/usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston/transports/console.js:46:3)
      at [object Object].log (/usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston/logger.js:102:17)
      at Object.log (/usr/local/lib/node/.npm/winston/0.2.7/package/lib/winston.js:53:34)
      at Object.<anonymous> (/Users/maraksquires/dev/winston/test.js:3:9)
      at Module._compile (module.js:404:26)
      at Object..js (module.js:410:10)
      at Module.load (module.js:336:31)
      at Function._load (module.js:297:12)

I'm assuming this is a simple fix. What do you think indexzero?

TypeError: Property 'defaultTransports' of object #<Object> is not a function

I believe this is a bug in winston >= 0.3.0 but it's possible it's a bug in forever > 0.5.6.

forever 0.5.5 and winston 0.2.11 work fine, but after upgrading to foroever 0.5.6 (which depends on winston >= 0.3.0 ) I see:

$ forever list

node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Property 'defaultTransports' of object # is not a function
at Object. (/usr/local/lib/node_modules/forever/bin/forever:172:9)
at Module._compile (module.js:407:26)
at Object..js (module.js:413:10)
at Module.load (module.js:339:31)
at Function._load (module.js:298:12)
at Array. (module.js:426:10)
at EventEmitter._tickCallback (node.js:126:26)

Uninstalling forever and reinstalling the same version did not help. I backed up through all the recent versions and the latest version that works is forever 0.5.5 with winston 0.2.11.

Allow shared transports across containers

Reported by @gitfy

I adapted my code based on the support for categories.

But the problem i came across was, it drastically slow down my application. The reason was, my transport is a Hook.io object whose so purpose is to publish the log messages out for someone who is listening.

What is happening with the container implementation is, whenever you request a categories, you are basically given a logger for which a transport is created all the time even though if the same transport is used cross all the loggers.

This kind of explodes the number of transport objects (in my case hooks) that drastically slows down.

What i feel would be kind of useful is, a way to re-use the transport objects across different loggers and each transport should also be given the information about which logger is calling the transport log method. This way one could add the information about the category or location information in the log details which will help to narrow down the logs during troubleshooting.

You might be able to test this out with the webhook transport which you have and a bunch of loggers using it as a transport.

Logging categories

Hi,
Is there way the library supports logging in different categories, just like in Java (based on packages).

This way, one could log things more isolated and search for them and also have different logging levels at different categories for troubleshooting purpose.

Thanks.

ANSI Color Codes being logged to log files

@indexzero

I'd like to fix the issue of colors.js logging ANSI color codes when logging to disk or any transport aside from the console.

I'm trying to formulate the best way to do this. I was thinking that I could patch colors.js to do a TTY detection and then simply have all "mystring".mycolor calls return "mystring" without any ANSI codes if a TTY is not available.

What do you think? Do you think my idea solves the issue in the right place?

  • Marak

Log entries with timestamp

Hi,
I am using your logging API with mongo-db transport. I would like have my log entries timestamped.

How can i accomplish this ? Can you help.
Thanks.

custom timestamps prevented - changes at odds with each other

Recent change (indexzero (author) July 24, 2011)

[api] Allow `options.timestamp` to be a custom function. Fixes #23
-  var output      = options.timestamp ? timestamp() + ' - ' : '';
+  var prefixfn    = typeof options.timestamp === 'function' ? options.timestamp : timestamp,
+      output      = options.timestamp ? prefixfn() + ' - ' : '',

attempted to make it possible for users to specify their own function to generate displayed timestamps.

Unfortunately previous recent changes made that impossible. An example change is (indexzero (author) July 18, 2011)

[api test] Finish work on rolling logs in the File transport
-  this.timestamp = options.timestamp || true;
+  this.timestamp = options.timestamp === true;

This code in console and other transports prevents a function value from filtering through and being seen by internal.js log() function. I assume the change from defaulting to true was intentional?

memory issue?

Node is warning me about a possible memory leak caused by winston.

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace: 
    at [object Object].<anonymous> (events.js:126:17)
    at [object Object].once (events.js:147:8)
    at /home/small/xavier/node_modules/winston/lib/winston/transports/file.js:124:19
    at [object Object].open (/home/small/xavier/node_modules/winston/lib/winston/transports/file.js:159:3)
    at [object Object].log (/home/small/xavier/node_modules/winston/lib/winston/transports/file.js:115:10)
    at [object Object].log (/home/small/xavier/node_modules/winston/lib/winston/logger.js:164:17)
    at [object Object].info (/home/small/xavier/node_modules/winston/lib/winston/common.js:45:21)
    at /home/small/xavier/storm.js:193:9
    at /home/small/xavier/node_modules/curry/curry.js:30:16
    at Array.forEach (native)

storm.js is my script. In the stacktrace at /home/small/xavier/storm.js:193:9, I'm looping over about 500 strings in an array and for each one calling log.info('Parsed Request', {system: system.name}) where log is a winston.Logger instance.

I noticed other people had reported a similar issue with socket.io and supposedly this pull request solves the problem: http://github.com/LearnBoost/socket.io/pull/161

I think I'm just making too many calls too quickly and I probably shouldn't try to write so much all at once, but wasn't sure if I should be expecting what I'm seeing.

cannot find module winston

what the hell? using node 0.4.0... i've just installed winston using "sudo npm install winston".
I cannot even require winston module, it breaks...

  node.js:116
        throw e; // process.nextTick error, or 'error' event on first tick
        ^
Error: Cannot find module 'winston'
    at Function._resolveFilename (module.js:289:11)
    at Function._load (module.js:241:25)
    at require (module.js:317:19)
    at Object.<anonymous> (/home/demian/www/projects/bankaccount/test.js:1:77)
    at Module._compile (module.js:373:26)
    at Object..js (module.js:379:10)
    at Module.load (module.js:305:31)
    at Function._load (module.js:271:10)
    at Array.<anonymous> (module.js:392:10)
    at EventEmitter._tickCallback (node.js:108:26)

improve "Extending another object with Logging functionality"

Hi,

I'm trying to migrate an existing app to use winston. In that app there is code like the one below which is very similar to what winston.extend(myObject) does, but with the difference that the context is automatically set based on a myObject property. In the case below it is the transaction.uuid. I understand that I'm manually able to set the context, but I'd like to have it in a single place and instead of setting the context with every log statement.

for (var key in logger) {
if (key.match(/^log\w/)) {
Connection.prototype[key] = (function (key) {
return function () {
var args = [ (this.transaction ? this.transaction.uuid : this.uuid) + " " ];
for (var i=start, l=arguments.length; i<l; i++) {
args.push(arguments[i]);
}
logger[key].apply(logger, args);
}
})(key);
}
}

it would nice if winston would allow something like

logger.extend(myObject, function (logger, logargs, metadata) {
// logger is the winston object used to log the statement
// logargs the arguments provided to log()
logger.metadata.xyz = 1234;
logger.withContext(this.transaction ? this.transaction.uuid : this.uuid);
});

thanks for considering

Named Instances + Logging Levels?

Really enjoying using this library... thanks again for the recommendation!

One of the features I love in log4js is the ability to set logging levels for specific "named" loggers. It makes it easy to, say, monitor a misbehaving module or particular portion of code, all from configuration. This proves invaluable in production, where I can alter a particular config at runtime for a set period.

Is there an analog to this functionality in Winston? Is this the purpose of "categories"? Can the log levels for a category be set in configuration, rather than in code?

I assume there is a way to code this manually, but I was wondering there was a pattern, if I was missing something simple native to Winston, or if this would be a good feature to add. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.