Writing to the syslog with Winston[source]

xml
<glacius:metadata>
    <title>Writing to the syslog with Winston</title>
    <description>NodeJS logging with Winston and syslog</description>
    <category>Legacy blog posts</category>
    <category>Programming</category>
    <category>JavaScript</category>
    <category>Node.js</category>
</glacius:metadata>
<glacius:macro name="legacy blargh banner">
    <properties>
        <originalUrl>https://tmont.com/blargh/2013/12/writing-to-the-syslog-with-winston</originalUrl>
        <originalDate>2013-12-24T04:05:46.000Z</originalDate>
    </properties>
</glacius:macro>
<p>
  <strong>Update:</strong> this code is now in its own 
  <a href="https://github.com/tmont/winston-syslog">GitHub repository</a>.
</p>
<hr />
<p>
  Many log aggregators (such as <a href="https://papertrailapp.com/">Papertrail</a> 
  or <a href="https://www.loggly.com/">Loggly</a>) have the ability to parse data from the
  syslog. This is often more convenient than writing to a file, handling
  rotation of said log file, handling archival of said rotated log file, and a 
  myriad of other annoyances. Plus, many other system programs (ssh, cron, etc.)
  already log stuff to the syslog, so most things are already aggregated.
</p>
<p>
  I use <a href="https://github.com/flatiron/winston">Winston</a> as my logging library
  for Node. It works pretty well inasmuch as it lets you log stuff. Winston exposes a
  <code>Transport</code> object, which is an interface to a logging destination (a file,
  the console, a webhook, etc.). You can use this to log to the syslog.
</p>
<p>
  Note that there are other modules for Winston that expose a syslog transport, but
  they all made me nervous, in that they weren't tested, and after glancing through
  the code, I wasn't convinced they were doing proper socket management. And the last
  thing I wanted was my logging library to create hundreds of undisposed file descriptors.
  So I decided to use <a href="https://github.com/melor/node-posix">node-posix</a> and just
  use the OS to write to the syslog rather than UDP. Plus <code>syslogd</code> doesn't
  have datagram support enabled by default, so you need to tweak the configuration to make
  it accept UDP packets, and I don't know enough about syslog to feel confident in messing
  with the configuration. And also I didn't feel like spending an hour learning about it.
  Because I'm weak and stupid.
</p>
<p>
  Anyway, here's some sample code to write to the syslog using the OS's POSIX functions.
</p>
<glacius:code lang="javascript"><![CDATA[
var winston = require('winston'),
	util = require('util'),
	posix = require('posix');
function SyslogTransport(options) {
	options = options || {};
	winston.Transport.call(this, options);
	this.id = options.id || process.title;
	this.facility = options.facility || 'local0';
	this.showPid = !!options.showPid;
}
util.inherits(SyslogTransport, winston.Transport);
util._extend(SyslogTransport.prototype, {
	name: 'syslog',
	log: function(level, msg, meta, callback) {
		if (this.silent) {
			callback(null, true);
			return;
		}
		if (level === 'error') {
			level = 'err';
		} else if (level === 'warn') {
			level = 'warning';
		}
		var message = '[' + level + '] ' + msg;
		if (typeof(meta) === 'string') {
			message += ' ' + meta;
		} else if (meta && typeof(meta) === 'object' && Object.keys(meta).length > 0) {
			message += ' ' + util.inspect(meta, false, null, false);
		}
		message = message.replace(/\u001b\[(\d+(;\d+)*)?m/g, '');
		var options = {
			cons: true,
			pid: this.showPid
		};
		posix.openlog(this.id, options, this.facility);
		posix.syslog(level, message);
		posix.closelog();
		callback(null, true);
	}
});
module.exports = SyslogTransport;
]]></glacius:code>
<p>
  And you could use it like so:
</p>
<glacius:code lang="javascript"><![CDATA[
var transport = new SyslogTransport({
	level: 'debug',
	id: 'hello syslog',
	facility: 'user',
	showPid: true
});
var log = new winston.Logger({
	level: 'debug',
	transports: [ transport ]
});
log.info('hello world');
]]></glacius:code>
<p>
  And then if you run <code>tail /var/log/syslog</code> (<code>/var/log/messages</code> 
  on OS X, I think), you should see something like this:
</p>
<glacius:code lang="plaintext"><![CDATA[
Dec 23 12:01:50 mesia hello syslog[17605]: [info] hello world
]]></glacius:code>