未验证 提交 36fb1f6a 编写于 作者: J Jialin, Sun 提交者: GitHub

Merge pull request #1519 from stdrickforce/nodejs

[Node.js] Add .eslintrc and fix warnings.
cmake*/
build/
package-lock.json
......@@ -2,6 +2,49 @@
`nodecat` supports node v8+.
## Changelog
### 3.1.0
As everybody knows that node.js is an event-driven programming language. It's hard for us to trace messages.
Transactions can be intersected, makes it impossible to know which transaction is the parent of another one.
It caused problems, so we fallback the default mode to **atomic**, which means all messages will be sent immediately after it has been completed.
As the message tree is useful in some cases, we have introduced a brand new **Thread Mode** in this version.
In this mode, the **first** transaction will be the **root** transaction, all the following transactions and events will become its child nodes. Instead of being sent after themselves have been completed, the entire message tree will be sent after the root transaction (their parent) has been completed.
Here is the example usage.
```js
var cat = require('../lib')
cat.init({
appkey: 'nodecat'
})
cat = new cat.Cat(true)
let a = cat.newTransaction("Context", "A")
let b = cat.newTransaction("Context", "B")
let c = cat.newTransaction("Context", "C")
setTimeout(function() {
b.complete()
}, 1000)
setTimeout(function() {
c.complete()
}, 1500)
setTimeout(function() {
a.complete()
console.log("a complete")
}, 2000)
```
## Requirements
The `nodecat` required `libcatclient.so` to be installed in `LD_LIBRARY_PATH`.
......
......@@ -2,6 +2,49 @@
`nodecat` 支持 node v8 及以上版本。
## Changelog
### 3.1.0
众所周知,node.js 是一个事件驱动的编程语言,这使得我们很难追踪消息。
Transaction 可以交错,令我们无法得知谁是谁的父节点。
这造成了一些问题,因此我们将默认模式降级为**原子模式**, 所有的消息在 complete 之后都会被立刻发送。
然而消息树在一些场景下很有用,因此我们在这个版本提供了一种船新的**线程模式**
在这一模式下,第一个 transaction 将会被作为根结点,随后所有的 transaction 和 event 都会被作为子节点。他们不会在 complete 之后被发送,取而代之的是在根结点 complete 后,整个消息树都会被发送。
这里有个例子:
```js
var cat = require('../lib')
cat.init({
appkey: 'nodecat'
})
cat = new cat.Cat(true)
let a = cat.newTransaction("Context", "A")
let b = cat.newTransaction("Context", "B")
let c = cat.newTransaction("Context", "C")
setTimeout(function() {
b.complete()
}, 1000)
setTimeout(function() {
c.complete()
}, 1500)
setTimeout(function() {
a.complete()
console.log("a complete")
}, 2000)
```
## Requirements
`nodecat` 需要 `libcatclient.so` 被安装在 `LD_LIBRARY_PATH` 目录下。
......
......@@ -23,3 +23,5 @@ for (var i = 0; i < 10; i++) {
// In this case, the object will be dumped into json.
cat.logEvent("Event", "E5", "failed", {a: 1, b: 2})
}
console.log('event end')
var cat = require('../lib')
cat.init({
appkey: 'nodecat'
})
cat = new cat.Cat(true)
let a = cat.newTransaction("Context", "A")
let b = cat.newTransaction("Context", "B")
let c = cat.newTransaction("Context", "C")
setTimeout(function() {
b.complete()
}, 1000)
setTimeout(function() {
c.complete()
}, 1500)
setTimeout(function() {
a.complete()
console.log("a complete")
}, 2000)
......@@ -7,7 +7,7 @@ const TreeManager = require('./message/org/tree-manager')
const STATUS = require('./constant').STATUS
const system = require('./system')
let isInitialized = false;
let isInitialized = false
class TransactionHandler {
constructor(transactionMessage, catInstance, threadMode) {
......@@ -29,7 +29,7 @@ class TransactionHandler {
/**
* Add data to a transaction.
* 序列化成 query的形式 &key=value
* 序列化成 query 的形式 &key=value
* 允许多次addData
* @param {string} key , 如果value存在则作为key,否则作为完整的data
* @param {string} [value]
......@@ -48,10 +48,9 @@ class TransactionHandler {
/**
* end a transaction.
* @param {number} maxTime
*/
complete(maxTime) {
this.treeManager.endMessage(this.message, maxTime)
complete() {
this.treeManager.endMessage(this.message)
}
/**
......@@ -76,12 +75,11 @@ class TransactionHandler {
if (this.threadMode) {
this.message.addChild(message)
}
let t = new TransactionHandler(message, this.cat, this.threadMode)
return t
return new TransactionHandler(message, this.cat, this.threadMode)
}
/**
* logError , 同cat.logError , 但确保挂在此transaction下
* logError , 同 cat.logError , 但确保挂在此transaction下
*/
logError(name, error) {
let message = this.message
......@@ -96,7 +94,7 @@ class TransactionHandler {
/**
* Class Cat
* 暴露给用户的API在这边,以这里的参数说明为准
* */
*/
class Cat {
constructor(threadMode) {
this.STATUS = STATUS
......@@ -155,13 +153,12 @@ class Cat {
newTransaction(type, name) {
type = '' + type
name = '' + name
var message = new TransactionMessage({
let message = new TransactionMessage({
type: type,
name: name
})
this.treeManager.addMessage(message)
let t = new TransactionHandler(message, this, this.threadMode)
return t
return new TransactionHandler(message, this, this.threadMode)
}
complete() {
......
......@@ -3,13 +3,14 @@ const os = require('os')
const logger = require('./logger.js')('config')
const getLocalIP = () => {
var ip = process.env.HOST_IP
let ip = process.env.HOST_IP
if (!ip) {
var interfaces = os.networkInterfaces()
var addresses = []
for (var k in interfaces) {
for (var k2 in interfaces[k]) {
var address = interfaces[k][k2]
let interfaces = os.networkInterfaces()
let addresses = []
for (let k of Object.values(interfaces)) {
for (let k2 of k) {
let address = k2
if (address.family === 'IPv4' && !address.internal) {
addresses.push(address.address)
}
......@@ -22,7 +23,7 @@ const getLocalIP = () => {
}
// exports
var config = {
let config = {
maxMessageLength: 2000,
hostname: os.hostname(),
domain: 'node-cat',
......
......@@ -4,10 +4,11 @@ const Event = require('../message/event')
exports.init = (appKey) => {
CCatApi.init(appKey)
process.on('exit', (code) => {
process.on('exit', () => {
try {
CCatApi.destroy()
} catch (e) {
// do nothing.
}
})
}
......
module.exports = function (filename) {
module.exports = function () {
return {
error: function (msg) {
console.log(msg);
console.log(msg)
},
info: function (msg) {
console.log(msg);
console.log(msg)
},
warn: function (msg) {
console.log(msg);
console.log(msg)
}
}
}
\ No newline at end of file
'use strict'
var Message = require('./message')
let Message = require('./message')
/**
* Get an instance of an event
......
'use strict'
var Message = require('./message')
var config = require('../config')()
let Message = require('./message')
let config = require('../config')()
class Heartbeat extends Message {
constructor(options) {
......
'use strict'
var HOUR = 3600 * 1000
var cluster = require('cluster')
var config = require('../config')()
var assert = require('assert')
var os = require('os')
let HOUR = 3600 * 1000
let cluster = require('cluster')
let config = require('../config')()
let assert = require('assert')
let os = require('os')
var cpuCount = os.cpus().length
let cpuCount = os.cpus().length
var seq = initialSeq()
var hourTS
let seq = initialSeq()
let hourTS
let defaultIpHex
var defaultIpHex
if (config.ip) {
var ips = config.ip.split('.')
let ips = config.ip.split('.')
assert.equal(ips.length, 4, 'ip must contains 4 groups')
var buffer = new Buffer(4)
for (var i = 0; i < 4; ++i) {
let buffer = new Buffer(4)
for (let i = 0; i < 4; ++i) {
buffer.writeUInt8(parseInt(ips[i]), i)
}
defaultIpHex = ''
for (var j = 0; j < buffer.length; j++) {
var b = buffer.readUInt8(j)
for (let j = 0; j < buffer.length; j++) {
let b = buffer.readUInt8(j)
defaultIpHex += ((b >> 4) & 0x0f).toString(16)
defaultIpHex += (b & 0x0f).toString(16)
}
}
module.exports.nextId = function (domain) {
var ts = Math.floor(Date.now() / HOUR)
let ts = Math.floor(Date.now() / HOUR)
if (ts != hourTS) {
if (ts !== hourTS) {
seq = initialSeq()
hourTS = ts
}
......@@ -51,14 +53,14 @@ function MessageId(domain, hexIp, timestamp, index) {
module.exports.parse = function (messageId) {
if (!messageId) return null
var list = messageId.split('-')
var len = list.length
let list = messageId.split('-')
let len = list.length
if (len >= 4) {
var ipAddressInHex = list[len - 3]
var timestamp = parseInt(list[len - 2])
var index = parseInt(list[len - 1])
var domain = list.splice(0, len - 3).join('-')
let ipAddressInHex = list[len - 3]
let timestamp = parseInt(list[len - 2])
let index = parseInt(list[len - 1])
let domain = list.splice(0, len - 3).join('-')
return new MessageId(domain, ipAddressInHex, timestamp, index)
}
......@@ -66,12 +68,13 @@ module.exports.parse = function (messageId) {
}
module.exports.getIpAddress = function () {
var local = this.hexIp
var i = []
for (var i = 0, len = local.length; i < len; i += 2) {
var first = local.charAt(i)
var next = local.charAt(i + 1)
var temp = 0
let local = this.hexIp
let ips = []
for (let i = 0, len = local.length; i < len; i += 2) {
let first = local.charAt(i)
let next = local.charAt(i + 1)
let temp = 0
if (first >= '0' && first <= '9') {
temp += (first - '0') << 4
......@@ -85,10 +88,10 @@ module.exports.getIpAddress = function () {
temp += (next - 'a') + 10
}
i.push(temp)
ips.push(temp)
}
return i.join('.')
return ips.join('.')
}
function initialSeq() {
......
......@@ -53,43 +53,31 @@ class Message {
this.beginTimestamp = +this.beginTime
}
end(maxTime) {
end() {
if (this.isEnd) {
return
}
this.isEnd = true
let now = new Date()
if (maxTime) {
if (now - this.beginTime > maxTime) {
this.endTime = new Date(+this.beginTime + maxTime)
} else {
this.endTime = now
}
} else {
this.endTime = now
}
this.endTime = new Date()
this.endTimestamp = +this.endTime
}
addChild(message) {
var self = this
Array.prototype.forEach.call(arguments, message => {
self.children.push(message)
// message.parent = self
addChild(...args) {
args.forEach(message => {
this.children.push(message)
// 如果当前的已经结束,但是加进来的节点没有end
if (self.allEnd && !message.isAllEnd()) {
self.allEnd = false
if (this.allEnd && !message.isAllEnd()) {
this.allEnd = false
}
})
}
removeChild() {
var children = this.children
Array.prototype.forEach.call(arguments, message => {
var index = children.indexOf(message)
removeChild(...args) {
args.forEach(message => {
let index = this.children.indexOf(message)
if (index > -1) {
children.splice(index, 1)
this.children.splice(index, 1)
message.parent = null
}
})
......@@ -97,7 +85,7 @@ class Message {
}
/**
* 是否自己和子节点全部都已经End
* 是否自己和子节点全部都已经End
*/
isAllEnd() {
if (this.allEnd) {
......
'use strict'
var Tree = require('./tree')
var Event = require('../event')
var Transaction = require('../transaction')
var Heartbeat = require('../heartbeat')
let Tree = require('./tree')
let Event = require('../event')
let Transaction = require('../transaction')
let Heartbeat = require('../heartbeat')
class TreeManager {
constructor(sender, threadMode) {
......@@ -51,9 +51,9 @@ class TreeManager {
/**
* 非线程模式,直接发送消息
*/
endMessage(message, maxTime) {
endMessage(message) {
// 先end自己
message.end(maxTime)
message.end()
if (!(message instanceof Transaction)) {
return
......
......@@ -4,15 +4,15 @@ var moment = require('moment')
function date2str(date) {
return moment(date).format('YYYY-MM-DD HH:mm:ss.SSS')
};
}
function durationInMillis(start, end) {
return (end - start)
};
}
function durationInMicros(start, end) {
return (end - start) * 1000
};
}
module.exports = {
date2str: date2str,
......
/**
* user child process to get disk space
* */
'use strict'
const exec = require('../util/shell').exec
const fs = require('fs')
......@@ -15,11 +12,11 @@ if (process.platform === 'linux' ||
return null
}
try {
var res = yield exec("df -k '" + drive.replace(/'/g, "'\\''") + "'")
var lines = res.trim().split('\n')
let res = yield exec('df -k \'' + drive.replace(/'/g, '\'\\\'\'') + '\'')
let lines = res.trim().split('\n')
var strDiskInfo = lines[lines.length - 1].replace(/[\s\n\r]+/g, ' ')
var diskInfo = strDiskInfo.split(' ')
let strDiskInfo = lines[lines.length - 1].replace(/[\s\n\r]+/g, ' ')
let diskInfo = strDiskInfo.split(' ')
return {
available: diskInfo[3] * 1024,
......
/**
* 获取系统的memory swap buffer/cache 使用情况
* 单位为byte
* */
'use strict'
var exec = require('../util/shell').exec
var os = require('os')
let exec = require('../util/shell').exec
let os = require('os')
const DEFAULT_RESULT = {
totalMem: 0,
......
'use strict'
/**
* Base Class for System info
* */
class SystemBaseInfo {
constructor(name, properties, content) {
this.name = name
......@@ -13,8 +10,8 @@ class SystemBaseInfo {
toString() {
// to xml item
var tag = '<' + this.name
var attrKeys = Object.keys(this.attrs)
let tag = '<' + this.name
let attrKeys = Object.keys(this.attrs)
if (attrKeys.length) {
tag += (' ' + attrKeys.map(key => key + '=' + '"' + this.attrs[key] + '"').join(' '))
}
......
......@@ -5,12 +5,12 @@ const Time = require('../message/util/time')
const Disk = require('./Disk')
const Mem = require('./Memory')
var userName = ''
if (os.userInfo) {
userName = os.userInfo().username
} else {
userName = require('child_process').execSync('whoami', {encoding: 'utf8', timeout: 1000}).replace('\n', '')
}
// let userName = ''
// if (os.userInfo) {
// userName = os.userInfo().username
// } else {
// userName = require('child_process').execSync('whoami', {encoding: 'utf8', timeout: 1000}).replace('\n', '')
// }
/**
* @return {SystemInfo} base system info
......
......@@ -9,13 +9,13 @@ let config = require('./config')()
exports.collectStart = function (cat) {
if (process.env && process.env.pm_id) {
// in pm2 , only one worker does this collection
// start exact one worker to collect cpu info in pm2.
try {
if (process.env.pm_id % os.cpus().length !== 0) {
return
}
} catch (e) {
return
}
}
......
{
"name": "nodecat",
"version": "3.0.0",
"version": "3.1.0",
"description": "Cat client for Node.js.",
"main": "index.js",
"scripts": {
......@@ -20,7 +20,8 @@
"mkdirp": "^0.5.1",
"moment": "^2.10.6",
"request": "^2.67.0",
"xml2js": "^0.4.15"
"xml2js": "^0.4.15",
"co": "latest"
},
"devDependencies": {
"cz-conventional-changelog": "^2.0.0",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册