Authored by 周奇琪

modify to es6

# influxdb-winston
## What is this?
A InfluxDB transport for winston by TCP or UDP.
## Installation
``` bash
mkdir test-influxdb-winston
cd test-influxdb-winston
npm init
npm install winston -save
npm install influxdb-winston -save
vi app.js
```
## Useage
`app.js`
```javascript
var winston = require('winston');
var influxdb =require('../index');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.TcpTransport)({ //send by tcp
level:'info', //logger level
host:'192.168.102.162', //influxdb host
port:'8016',//influxdb port
database:'log5',//influxdb database
measurement:'example'//influxdb measurement
}),
new (winston.transports.UdpTransport)({ //send by udp
level:'debug', //logger level
host:'192.168.102.162', //influxdb host
port:'4444'//influxdb port
}),
new (winston.transports.Console)()
]
});
logger.log('info', 'Hello distributed log files!','dasda');
logger.info('Hello again distributed logs');
logger.level = 'debug';
logger.log('error', 'Now my debug messages are written to console!');
logger.log('debug', 'Ncze!');
setTimeout(function(){
logger.log('info','lalala');
},1000)
```
\ No newline at end of file
... ...
... ... @@ -2,13 +2,18 @@
var influxdb =require('../index');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.InfuxdbLogger)({
new (winston.transports.TcpTransport)({ //send by tcp
level:'info', //logger level
host:'192.168.102.162', //influxdb host
port:'8085',//influxdb port
port:'8016',//influxdb port
database:'log5',//influxdb database
measurement:'example'//influxdb measurement
}),
new (winston.transports.UdpTransport)({ //send by udp
level:'debug', //logger level
host:'192.168.102.162', //influxdb host
port:'4444'//influxdb port
}),
new (winston.transports.Console)()
]
});
... ...
var util = require('util'),
winston = require('winston'),
http = require("http"),
os = require('os');
/**
* add InfuxdbLogger to winston
* @param {Object} options logger options
* eg.
* {
* level:'warn' //logger level
* host:'127.0.0.1' //influxdb host
* port:'8085'//influxdb port
* database:'log'//influxdb database
* measurement:'api'//influxdb measurement
* }
*
* require main
*/
var InfuxdbLogger = winston.transports.InfuxdbLogger = function (options) {
var that = this;
this.name = 'infuxdbLogger';
this.level = options.level || 'info';
this.options = options;
this.logs = [];
initDatabase(this.options,function(){
that.isCreated = true;
that.options.line = false;
addLine(that);
});
};
util.inherits(InfuxdbLogger, winston.Transport);
//log transport
InfuxdbLogger.prototype.log = function (level, msg, meta, callback) {
if(!this.options.measurement) {
this.options.measurement = 'log';
}
//make influxdb create line
this.options.line = makeLine(this.options.measurement,level,msg,meta);
addLine(this);
callback(null,true);
};
/**
* make a request options
* @param {Object} opts
*/
function makeReq(opts,path,method) {
var options = {
"method": method,
"hostname": opts.host,
"port": opts.port || '8086',
"path": path
};
return options;
}
/**
* init database
* @param {Object} options logger config
* @param {Function} callback
*/
function initDatabase(options,callback) {
var path = "/query?q=CREATE%20DATABASE%20"+ (options.database||'log');
var opts = makeReq(options,path,'GET');
//send to influxdb create database
var req = http.request(opts,function(res){
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
callback(res,body.toString());
});
});
req.end();
}
/**
* insert a line to influxdb
* @param {Logger} logger logger
*/
function addLine(logger) {
var path = "/write?db="+ (logger.options.database||'log');
var options = makeReq(logger.options,path,'POST');
var line = logger.options.line;
var logs = logger.logs;
//if influxdb database uninit,add line to a array;
if(!logger.isCreated) {
logger.logs.push({
opts:options,
line:line
});
} else {
//send to influxdb
sendLine(options,line);
if(logs.length<1) {
return;
}
//send logs's line to influxdb
for(var i = 0; i<logs.length;i++) {
sendLine(logs[i].opts,logs[i].line);
}
// empty logs array.
logger.logs = [];
}
}
/**
* send to influxdb
* @param {Object} opts send options
* @param {String} line influxdb line
*/
function sendLine(opts,line) {
if(!line) {
return;
}
var req = http.request(opts);
req.write(line);
req.end();
}
/**
* format line protocol
* @param {String} measurement influxdb's measurement
* @param {String} level log level
* @param {String} msg log message
* @param {String} meta log meta
*/
function makeLine(measurement,level,msg,meta) {
if(typeof meta ==='object')
{
meta = JSON.stringify(meta);
}
//make tags
var tags = [
'host=' + os.hostname(),
'pid=' + process.pid,
'level=' + level,
]
var fields = [
'message="' + msg + '"',
'meta="' + meta + '"'
] ;
tags = tags.join(',');
fields = fields.join(',');
return measurement + ',' + tags + ' ' + fields;
}
\ No newline at end of file
const winston = require('winston'),
TcpTransport = require('./libs/TcpTransport'),
UdpTransport = require('./libs/UdpTransport');
winston.transports.TcpTransport = TcpTransport;
winston.transports.UdpTransport = UdpTransport;
... ...
"use strict";
//winston logger
const Transport = require('winston').Transport,
os = require('os');
/**
* @class BaseTranport
* @description Logger transport base class
* @author hbomb qiqi.zhou@gmail.com
*/
class BaseTranport extends Transport {
/**
* @description init options
*/
constructor(options) {
super(options);
this.level = options.level || 'info';
this.options = options;
this.logs = [];
}
/**
* @method log
* @description tranport log to influxdb
* @param {String} level log level
* @param {String} msg log message
* @param {Object} meta log meta object
* @param {Function} callback callback function
*/
log(level, msg, meta, callback) {
if (!this.options.measurement) {
this.options.measurement = 'log';
}
//make influxdb create line
this.options.line = this.makeLine(this.options.measurement, level, msg, meta);
this.addLine();
callback(null, true);
}
/**
* @method addLine
* @description abstract method,for sub class implement
*/
addline() {
}
/**
* @method makeLine
* @description format line protocol
* @param {String} measurement influxdb's measurement
* @param {String} level log level
* @param {String} msg log message
* @param {String} meta log meta
*/
makeLine(measurement, level, msg, meta) {
//if meta is object to string.
if (typeof meta === 'object') {
meta = JSON.stringify(meta);
}
//make tags
let tags = [
'host=' + os.hostname(),
'pid=' + process.pid,
'level=' + level,
]
//make fields
let fields = [
'message="' + msg + '"',
'meta="' + meta + '"'
];
//make a line
tags = tags.join(',');
fields = fields.join(',');
return measurement + ',' + tags + ' ' + fields;
}
}
module.exports = BaseTranport;
... ...
"use strict";
//Base Class for influxdb trabsport
const BaseTransport = require('./BaseTransport'),
http = require('http');
//for make influxdb query string
const CREATE_DATA_BASE = "/query?q=CREATE%20DATABASE%20";
const ADD_LINE_PREIX = "/write?db=";
/**
* @class TcpTransport
* @author hbomb qiqi.zhou@gmail.com
*/
class TcpTransport extends BaseTransport {
/**
* @description init options and init database
* @example {
* level:'warn' //logger level
* host:'127.0.0.1' //influxdb host
* port:'8085'//influxdb port
* database:'log'//influxdb database
* measurement:'api'//influxdb measurement
* }
*/
constructor(options) {
super(options);
this.name = "tcpInfuxdbLogger";
let that = this;
this.initDatabase(function () {
that.isCreated = true;
that.options.line = false;
that.addLine();
});
}
/**
* @method initDatabase
* @description init database
* @param {Function} callback
*/
initDatabase(callback) {
let path = CREATE_DATA_BASE + (this.options.database || 'log');
let opts = this.makeReq(path, 'GET');
//send to influxdb create database
let req = http.request(opts, function (res) {
let chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
let body = Buffer.concat(chunks);
callback(res, body.toString());
});
});
req.end();
}
/**
* make a request options
* @param {String} path send path
* @param {String} method http method
*/
makeReq(path, method) {
let opts = this.options,
options = {
"method": method,
"hostname": opts.host,
"port": opts.port || '8086',
"path": path
};
return options;
}
/**
* @method addLine
* @description insert a line to influxdb
*/
addLine() {
let logger = this,
path = ADD_LINE_PREIX + (logger.options.database || 'log'),
options = this.makeReq(path, 'POST'),
line = logger.options.line,
logs = logger.logs;
//if influxdb database uninit,add line to a array;
if (!logger.isCreated) {
logger.logs.push({
opts: options,
line: line
});
} else {
//send to influxdb
this.sendLine(options,line);
if (logs.length < 1) {
return;
}
//send logs's line to influxdb
for (var i = 0; i < logs.length; i++) {
this.sendLine(logs[i].opts,logs[i].line);
}
// empty logs array.
logger.logs = [];
}
}
/**
* @method sendLine
* @description send to influxdb
* @param {Object} options request
* @param {String} line influxdb line
*/
sendLine(options,line) {
if (!line) {
return;
}
let req = http.request(options);
req.write(line);
req.end();
}
}
module.exports = TcpTransport;
\ No newline at end of file
... ...
"use strict";
//Base Class for influxdb trabsport
const BaseTransport = require('./BaseTransport'),
dgram = require("dgram");
/**
* @class UdpTransport
* @author hbomb qiqi.zhou@gmail.com
*/
class UdpTransport extends BaseTransport {
/**
* @description init options and init database
* @example {
* level:'warn' //logger level
* host:'127.0.0.1' //influxdb host
* port:'4444'//influxdb port
* measurement:'api'//influxdb measurement
* }
*/
constructor(options) {
super(options);
this.name = "udpInfuxdbLogger";
}
/**
* @method addLine
* @description insert a line to influxdb
*/
addLine() {
let socket=dgram.createSocket("udp4"),
opts = this.options,
line = this.options.line,
buf=new Buffer(line),
length = buf.length;
socket.send(buf, 0, length, opts.port,opts.host, function () {
socket.close();
});
}
}
module.exports = UdpTransport;
\ No newline at end of file
... ...
{
"name": "influxdb-winston",
"version": "1.0.0",
"description": "",
"description": "A InfluxDB transport for winston by TCP or UDP.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "mocha --reporter spec"
},
"author": "",
"license": "ISC",
"author": "hbomb",
"license": "MIT",
"dependencies": {
"winston": "^2.2.0"
}
... ...
require('./libs/BaseTransport.test');
require('./libs/TcpTransport.test');
require('./libs/UdpTransport.test');
\ No newline at end of file
... ...