128 lines
3.5 KiB
JavaScript
128 lines
3.5 KiB
JavaScript
var gelfStream = exports
|
|
var gelfling = require('gelfling')
|
|
var util = require('util')
|
|
var Writable = require('stream').Writable
|
|
|
|
function GelfStream(host, port, options) {
|
|
if (options == null && typeof port === 'object') {
|
|
options = port
|
|
port = null
|
|
if (options == null && typeof host === 'object') {
|
|
options = host
|
|
host = null
|
|
}
|
|
}
|
|
if (options == null) options = {}
|
|
|
|
if (options.keepAlive == null) options.keepAlive = true
|
|
|
|
Writable.call(this, {objectMode: true})
|
|
|
|
this._options = options
|
|
this._client = gelfling(host, port, options)
|
|
|
|
this.once('finish', this.destroy)
|
|
}
|
|
util.inherits(GelfStream, Writable)
|
|
|
|
GelfStream.prototype._write = function(chunk, encoding, callback) {
|
|
if (!this._options.filter || this._options.filter(chunk)) {
|
|
this._client.send(this._options.map ? this._options.map(chunk) : chunk, callback)
|
|
} else {
|
|
callback()
|
|
}
|
|
}
|
|
|
|
GelfStream.prototype.destroy = function(callback) {
|
|
if (callback) this.once('close', callback)
|
|
this._client.close()
|
|
process.nextTick(function() { this.emit('close') }.bind(this))
|
|
}
|
|
|
|
function create(host, port, options) {
|
|
return new GelfStream(host, port, options)
|
|
}
|
|
|
|
// ---------------------------
|
|
// Bunyan stuff
|
|
// ---------------------------
|
|
|
|
function mapGelfLevel(bunyanLevel) {
|
|
switch (bunyanLevel) {
|
|
case 10 /*bunyan.TRACE*/: return gelfling.DEBUG
|
|
case 20 /*bunyan.DEBUG*/: return gelfling.DEBUG
|
|
case 30 /*bunyan.INFO*/: return gelfling.INFO
|
|
case 40 /*bunyan.WARN*/: return gelfling.WARNING
|
|
case 50 /*bunyan.ERROR*/: return gelfling.ERROR
|
|
case 60 /*bunyan.FATAL*/: return gelfling.EMERGENCY
|
|
default: return gelfling.WARNING
|
|
}
|
|
}
|
|
|
|
function flatten(obj, into, prefix, sep) {
|
|
if (into == null) into = {}
|
|
if (prefix == null) prefix = ''
|
|
if (sep == null) sep = '.'
|
|
var key, prop
|
|
for (key in obj) {
|
|
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue
|
|
prop = obj[key]
|
|
if (typeof prop === 'object' && !(prop instanceof Date) && !(prop instanceof RegExp))
|
|
flatten(prop, into, prefix + key + sep, sep)
|
|
else
|
|
into[prefix + key] = prop
|
|
}
|
|
return into
|
|
}
|
|
|
|
function bunyanToGelf(log) {
|
|
/*jshint camelcase:false */
|
|
var errFile, key,
|
|
ignoreFields = ['hostname', 'time', 'msg', 'name', 'level', 'v'],
|
|
flattenedLog = flatten(log),
|
|
gelfMsg = {
|
|
host: log.hostname,
|
|
timestamp: +new Date(log.time) / 1000,
|
|
short_message: log.msg,
|
|
facility: log.name,
|
|
level: mapGelfLevel(log.level),
|
|
full_message: JSON.stringify(log, null, 2)
|
|
}
|
|
|
|
if (log.err && log.err.stack &&
|
|
(errFile = log.err.stack.match(/\n\s+at .+ \(([^:]+)\:([0-9]+)/)) != null) {
|
|
if (errFile[1]) gelfMsg.file = errFile[1]
|
|
if (errFile[2]) gelfMsg.line = errFile[2]
|
|
}
|
|
|
|
for (key in flattenedLog) {
|
|
if (ignoreFields.indexOf(key) < 0 && gelfMsg[key] == null)
|
|
gelfMsg[key] = flattenedLog[key]
|
|
}
|
|
|
|
return gelfMsg
|
|
}
|
|
|
|
function forBunyan(host, port, options) {
|
|
if (options == null && typeof port === 'object') {
|
|
options = port
|
|
port = null
|
|
if (options == null && typeof host === 'object') {
|
|
options = host
|
|
host = null
|
|
}
|
|
}
|
|
if (options == null) options = {}
|
|
|
|
options.map = bunyanToGelf
|
|
|
|
return new GelfStream(host, port, options)
|
|
}
|
|
|
|
gelfStream.GelfStream = GelfStream
|
|
gelfStream.create = create
|
|
gelfStream.forBunyan = forBunyan
|
|
gelfStream.bunyanToGelf = bunyanToGelf
|
|
gelfStream.mapGelfLevel = mapGelfLevel
|
|
gelfStream.flatten = flatten
|