diff --git a/fromlog.counter b/fromlog.counter new file mode 100644 index 0000000..e69de29 diff --git a/fromlog.datadefinition b/fromlog.datadefinition new file mode 100644 index 0000000..33236aa --- /dev/null +++ b/fromlog.datadefinition @@ -0,0 +1,81 @@ +module.exports = { + init: function(data){ + /* counter sample + data.name = {} + data.name.help = "help"; + data.name.type = "counter"; + data.name.value = 0; + */ + + /* gauge sample + data.name = {} + data.name.help = "help"; + data.name.type = "gauge"; + data.name.value= 0; + */ + + /* histogram sample + data.name = {} + data.name.help = "help"; + data.name.type = "histogram"; + data.name.bucket = {}; + data.name.sum = 0; + data.name.count = 0; + */ + + /* summary sample + + data.name = {} + data.name.help = "help"; + data.name.type = "summary"; + data.name.quantile = {}; + data.name.sum = 0; + data.name.count = 0; + */ + + + /* global label sample + data.__labels = {} + data.__labels.test1="aa"; + data.__labels.test2="bb"; + */ + + /* per metric label sample + data.name.labels = {} + data.name.labels.test3="aa"; + data.name.labels.test4="bb"; + */ + + + + return data; + }, + extractdatafromline: function(data,line){ + + /* counter sample + data.name.value++; + */ + + /* gauge sample + data.name.value= 10; + */ + + /* histogram sample + data.name.bucket["0.1"] = 3; + data.name.bucket["0.5"] = 5; + data.name.bucket["+Inf"] = 5; + data.name.sum = 1.3; + data.name.count = 5; + */ + + /* summary sample + data.name.quantile["0.95"] = 3; + data.name.sum = 1.3; + data.name.count = 5; + */ + + + return data; + + } +}; diff --git a/fromlog.file b/fromlog.file new file mode 100644 index 0000000..e69de29 diff --git a/fromlog.js b/fromlog.js new file mode 100644 index 0000000..12ad5da --- /dev/null +++ b/fromlog.js @@ -0,0 +1,98 @@ +var datadefinition = require("./fromlog.datadefinition" ); +var data = {}; +var fs = require('fs'), + bite_size = 4096, + save_interval_or_retry = 10000, + filereadbytes, + tempdata = "", + fd; + +function init(){ + fs.readFile('fromlog.counter',function(err, content){ + if (err){ + filereadbytes = 0; + }else{ + filereadbytes = parseInt(content); + if (isNaN(filereadbytes)){ + filereadbytes = 0; + } + } + var oldfilereadbytes = filereadbytes; + setInterval(function(){ + if (filereadbytes != oldfilereadbytes){ + fs.writeFile("fromlog.counter", filereadbytes.toString(),function(err){}); + oldfilereadbytes = filereadbytes; + } + }, save_interval_or_retry); + openandreadsome(); + }); +} + + +function openandreadsome(){ + fs.open('fromlog.file', 'r',function(err, file){ + if (err){ + return setTimeout(openandreadsome, save_interval_or_retry); + } + fd = file; + fs.fstat(file, function(err, stats){ + if (err || stats.size == filereadbytes){ + return fs.close(file,function(err){ + setTimeout(openandreadsome, save_interval_or_retry); + }); + } + if (stats.size < filereadbytes){ + filereadbytes =0; + } + readsome(stats); + }); + }); + +} + +function readsome(stats) { + + fs.read(fd, Buffer.alloc(bite_size), 0, bite_size, filereadbytes, function(err, actualbytesread, buffer){ + if (err){ + return fs.close(fd,function(err){ + setTimeout(openandreadsome, save_interval_or_retry); + }); + + } + if(actualbytesread == 0) { + return fs.close(fd,function(err){ + setTimeout(openandreadsome, save_interval_or_retry); + }); + } + processsome(actualbytesread,buffer); + readsome(stats); + }); + + +} + +function processsome(actualbytesread, buff) { + var datastring = buff.toString('utf-8', 0, actualbytesread); + tempdata+=datastring; + var tempdatasplit = tempdata.split(/\r\n|\r|\n/); + for (var i = 0; i < tempdatasplit.length - 1; i++) { + data= datadefinition.extractdatafromline(data,tempdatasplit[i]); + } + tempdata = tempdatasplit[tempdatasplit.length - 1]; + filereadbytes+= actualbytesread; +} + + +module.exports = { + init: function () { + init(); + data= datadefinition.init(data); + }, + data: function () { + return data; + } +}; + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..34ed472 --- /dev/null +++ b/index.js @@ -0,0 +1,62 @@ +var http = require('http'); +var modifier = process.env.MODIFIER; +if (modifier){ + modifier = require("./" + modifier ); + modifier.init(); + + http.createServer(function(req,res){ + res.writeHead(200,{"Content-Type": "text/plain"}); + var data = modifier.data(); + var body = ""; + var globallabelstring = ""; + if (data.__labels){ + for (var label in data.__labels) { + if (data.__labels.hasOwnProperty(label)){ + globallabelstring+=label + "=\"" + data.__labels[label] + "\","; + } + } + } + for (var prop in data) { + if (prop != "__labels" && data.hasOwnProperty(prop)) { + var labelstring = ""; + if (data[prop].labels){ + for (var label in data[prop].labels) { + if (data[prop].labels.hasOwnProperty(label)){ + labelstring+=label + "=\"" + data[prop].labels[label] + "\","; + } + } + } + body+="# HELP " + prop + " " + data[prop].help + "\n"; + if (data[prop].type == "counter"){ + body+="# TYPE " + prop + " counter" + "\n"; + body+=prop + "{" + globallabelstring + labelstring + "}" + " " + data[prop].value.toString() + "\n"; + }else if (data[prop].type == "gauge"){ + body+="# TYPE " + prop + " gauge" + "\n"; + body+=prop + "{" + globallabelstring + labelstring + "}" + " " + data[prop].value.toString() + "\n"; + }else if (data[prop].type == "histogram"){ + body+="# TYPE " + prop + " histogram" + "\n"; + for (var le in data[prop].bucket) { + if (data[prop].bucket.hasOwnProperty(le)){ + body+=prop + "_bucket{le=\""+ le + "\"," + globallabelstring + labelstring + "} " + data[prop].bucket[le].toString() + "\n"; + } + } + body+=prop + "_count{" + globallabelstring + labelstring + "} " + data[prop].count.toString()+ "\n"; + body+=prop + "_sum{" + globallabelstring + labelstring + "} " + data[prop].sum.toString()+ "\n"; + }else if (data[prop].type == "summary"){ + body+="# TYPE " + prop + " summary" + "\n"; + for (var q in data[prop].quantile) { + if (data[prop].quantile.hasOwnProperty(q)){ + body+=prop + "{quantile=\""+ q + "\"," + globallabelstring + labelstring + "} " + data[prop].quantile[q].toString() + "\n"; + } + } + body+=prop + "_count{" + globallabelstring + labelstring + "} " + data[prop].count.toString()+ "\n"; + body+=prop + "_sum{" + globallabelstring + labelstring + "} " + data[prop].sum.toString()+ "\n"; + } + } + } + res.end(body); + }).listen(80); +} else { + console.log("No modifier selected"); +} + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..83e1a1c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,38 @@ +{ + "name": "statist", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "http": "^0.0.1-security", + "line-reader": "^0.4.0" + } + }, + "node_modules/http": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", + "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" + }, + "node_modules/line-reader": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/line-reader/-/line-reader-0.4.0.tgz", + "integrity": "sha1-F+RIGNoKwzVnW6MAlU+U72cOZv0=" + } + }, + "dependencies": { + "http": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz", + "integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g==" + }, + "line-reader": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/line-reader/-/line-reader-0.4.0.tgz", + "integrity": "sha1-F+RIGNoKwzVnW6MAlU+U72cOZv0=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6bc3535 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "statist", + "version": "1.0.0", + "description": "collect data for prometheus", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "xgiovio", + "license": "ISC", + "dependencies": { + } +}