├── package.json ├── LICENSE ├── README.md └── lib └── node-syslog.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "syslog", 3 | "description" : "Syslog-ng TCP client, with basic fault-tolerance.", 4 | "url" : "http://github.com/cloudhead/node-syslog", 5 | "keywords" : ["syslog", "logger"], 6 | "author" : "Alexis Sellier ", 7 | "contributors" : [], 8 | "version" : "0.1.1-1", 9 | "main" : "./lib/node-syslog", 10 | "directories" : { "lib": "./lib" }, 11 | "engines" : { "node": ">=0.4.2" } 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Alexis Sellier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | node-syslog 3 | =========== 4 | 5 | > Syslog-ng TCP client for node, with basic fault-tolerance. 6 | 7 | installation 8 | ------------ 9 | 10 | $ npm install syslog 11 | 12 | synopsis 13 | -------- 14 | 15 | var syslog = require('syslog'); 16 | var logger = syslog.createClient(514, 'localhost'); 17 | 18 | logger.info("ping!"); 19 | 20 | log levels 21 | ---------- 22 | 23 | In increasing order of severity: 24 | 25 | - debug 26 | - info 27 | - notice 28 | - warning 29 | - error 30 | - crit 31 | - alert 32 | - emerg 33 | 34 | These are available as methods on Client, ex: `logger.crit()`. 35 | 36 | You may also call the `log` method, and pass the level as the 2nd argument: 37 | 38 | logger.log('fnord!', syslog.LOG_CRIT); 39 | 40 | The default level is `info`. 41 | 42 | configuration 43 | ------------- 44 | 45 | You will have to configure your syslog server to accept TCP connections. 46 | This is usually done in `/etc/syslog-ng.conf`. Let's say you have an app called `fnord`, 47 | the configuration would look something like this: 48 | 49 | source tcp_s { 50 | tcp(ip(0.0.0.0) port(514) max-connections(256)); 51 | }; 52 | destination fnord_d { 53 | file("/var/log/fnord.log"); 54 | }; 55 | log { source(tcp_s); destination(fnord_d); }; 56 | 57 | If you have multiple apps which need to log via TCP, you can specify filters, as such: 58 | 59 | filter fnord_f { program("fnord"); }; 60 | 61 | Then modify the log statement to read: 62 | 63 | log { source(tcp_s); filter(fnord_f); destination(fnord_d); }; 64 | 65 | Now if you have another app, called `bnord`, create similar `destination` and `filter` configurations for it, 66 | and specify a new log statement, with the same `source`: 67 | 68 | log { source(tcp_s); filter(bnord_f); destination(bnord_d); }; 69 | 70 | For this to work, you have to make sure you set the `process.title` variable in your node app. 71 | 72 | process.title = 'fnord'; 73 | 74 | Alternatively, you can pass it as an option to `createClient`: 75 | 76 | syslog.createClient(514, 'localhost', { name: 'fnord' }); 77 | 78 | license 79 | ------- 80 | 81 | See `LICENSE` file. 82 | 83 | > Copyright (c) 2011 Alexis Sellier 84 | 85 | -------------------------------------------------------------------------------- /lib/node-syslog.js: -------------------------------------------------------------------------------- 1 | var net = require('net'); 2 | var os = require('os'); 3 | // 4 | // node-syslog.js - TCP syslog-ng client 5 | // 6 | 7 | // Message severity levels 8 | this.LOG_EMERG = 0; 9 | this.LOG_ALERT = 1; 10 | this.LOG_CRIT = 2; 11 | this.LOG_ERROR = 3; 12 | this.LOG_WARNING = 4; 13 | this.LOG_NOTICE = 5; 14 | this.LOG_INFO = 6; 15 | this.LOG_DEBUG = 7; 16 | 17 | this.FACILITY_USER = 1; 18 | 19 | this.DEFAULT_OPTIONS = { 20 | facility: exports.FACILITY_USER, 21 | name: null, 22 | debug: false 23 | }; 24 | 25 | var hostname = os.hostname(); 26 | 27 | this.Client = function (port, host, options) { 28 | this.port = port || 514; 29 | this.host = host || 'localhost'; 30 | this.options = options || {}; 31 | 32 | for (var k in exports.DEFAULT_OPTIONS) { 33 | if (this.options[k] === undefined) { this.options[k] = exports.DEFAULT_OPTIONS[k] } 34 | } 35 | 36 | // We need to set this option here, incase the module is loaded before `process.title` is set. 37 | if (! this.options.name) { this.options.name = process.title || process.argv.join(' ') } 38 | 39 | this.socket = null; 40 | this.retries = 0; 41 | this.queue = []; 42 | }; 43 | this.Client.prototype = new(function () { 44 | var that = this; 45 | 46 | // Generate logging methods, such as `info`, `debug`, ... 47 | for (var k in exports) { 48 | if (/^LOG/.test(k)) { 49 | (function (level, name) { 50 | that[name] = function (msg) { 51 | this.log(msg, exports[level]); 52 | }; 53 | })(k, k.match(/^LOG_([A-Z]+)/)[1].toLowerCase()); 54 | } 55 | } 56 | 57 | this.log = function (msg, severity) { 58 | var that = this; 59 | msg = msg.trim(); 60 | severity = severity !== undefined ? severity : exports.LOG_INFO; 61 | 62 | if (severity === exports.LOG_DEBUG && !this.options.debug) { return } 63 | 64 | this.connect(function (e) { 65 | var pri = '<' + ((that.options.facility * 8) + severity) + '>'; // Message priority 66 | var entry = pri + [ 67 | new(Date)().toJSON(), 68 | hostname, 69 | that.options.name + '[' + process.pid + ']:', 70 | msg 71 | ].join(' ') + '\n'; 72 | 73 | // 74 | // If there's a connection problem, 75 | // queue the message for later processing. 76 | // 77 | if (e) { 78 | that.queue.push(entry); 79 | // Write the entry to the socket 80 | } else { 81 | that.socket.write(entry, 'utf8', function (e) { 82 | if (e) { that.queue.push(entry) } 83 | }); 84 | } 85 | }); 86 | }; 87 | this.connect = function (callback) { 88 | var that = this; 89 | 90 | callback = callback || function () {}; 91 | 92 | if (this.socket) { 93 | if (this.socket.readyState === 'open') { 94 | callback(null); 95 | } else { 96 | callback(true); 97 | } 98 | } else { 99 | callback(true); 100 | 101 | this.socket = net.createConnection(this.port, this.host); 102 | this.socket.setKeepAlive(true); 103 | this.socket.setNoDelay(); 104 | this.socket.on('connect', function () { 105 | that.socket.write(that.queue.join('')); 106 | that.queue = []; 107 | that.retries = 0; 108 | that.connected = true; 109 | }).on('error', function (e) { 110 | console.log(e.message); 111 | }).on('end', function (e) { 112 | }).on('close', function (e) { 113 | var interval = Math.pow(2, that.retries); 114 | that.connected = false; 115 | setTimeout(function () { 116 | that.retries ++; 117 | that.socket.connect(that.port, that.host); 118 | }, interval * 1000); 119 | }).on('timeout', function () { 120 | if (that.socket.readyState !== 'open') { 121 | that.socket.destroy(); 122 | } 123 | }); 124 | } 125 | }; 126 | }); 127 | 128 | this.createClient = function (port, host, options) { 129 | return new(this.Client)(port, host, options); 130 | }; 131 | 132 | --------------------------------------------------------------------------------