feat: 초기 프로젝트 설정 및 룰.md 파일 추가
This commit is contained in:
146
api.hyungi.net/node_modules/tx2/API.md
generated
vendored
Normal file
146
api.hyungi.net/node_modules/tx2/API.md
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
## Classes
|
||||
|
||||
<dl>
|
||||
<dt><a href="#TX2">TX2</a></dt>
|
||||
<dd></dd>
|
||||
</dl>
|
||||
|
||||
## Typedefs
|
||||
|
||||
<dl>
|
||||
<dt><a href="#Metric">Metric</a> : <code>Object</code></dt>
|
||||
<dd></dd>
|
||||
<dt><a href="#Counter">Counter</a> : <code>object</code></dt>
|
||||
<dd><p>Expose a metric of type: Counter.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<a name="TX2"></a>
|
||||
|
||||
## TX2
|
||||
**Kind**: global class
|
||||
|
||||
* [TX2](#TX2)
|
||||
* [.action(action_name, [opts], fn)](#TX2.action)
|
||||
* [.event(name, data)](#TX2.event)
|
||||
* [.issue(err)](#TX2.issue)
|
||||
* [.metric(name, [function])](#TX2.metric) ⇒ [<code>Metric</code>](#Metric)
|
||||
* [.counter(name)](#TX2.counter) ⇒ [<code>Counter</code>](#Counter)
|
||||
|
||||
<a name="TX2.action"></a>
|
||||
|
||||
### TX2.action(action_name, [opts], fn)
|
||||
Expose an action/function triggerable via PM2 or PM2.io
|
||||
|
||||
**Kind**: static method of [<code>TX2</code>](#TX2)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| action_name | <code>string</code> | Name of the action |
|
||||
| [opts] | <code>object</code> | Optional parameter |
|
||||
| fn | <code>function</code> | Function to be called |
|
||||
|
||||
**Example** *(Action without arguments)*
|
||||
```js
|
||||
tx2.action('run_query', (cb) => {
|
||||
cb({ success: true })
|
||||
})
|
||||
```
|
||||
**Example** *(Action with arguments)*
|
||||
```js
|
||||
tx2.action('run_query', arg1, (cb) => {
|
||||
cb({ success: arg1 })
|
||||
})
|
||||
```
|
||||
<a name="TX2.event"></a>
|
||||
|
||||
### TX2.event(name, data)
|
||||
Sends an Event
|
||||
|
||||
**Kind**: static method of [<code>TX2</code>](#TX2)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| name | <code>string</code> | Name of the event |
|
||||
| data | <code>object</code> | Metadata attached to the event |
|
||||
|
||||
**Example**
|
||||
```js
|
||||
tx2.event('event-name', { multi: 'data' })
|
||||
```
|
||||
<a name="TX2.issue"></a>
|
||||
|
||||
### TX2.issue(err)
|
||||
Sends an Issue
|
||||
|
||||
**Kind**: static method of [<code>TX2</code>](#TX2)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| err | <code>string</code> \| <code>Error</code> | Error object or string to notify |
|
||||
|
||||
**Example**
|
||||
```js
|
||||
tx2.issue(new Error('bad error')
|
||||
```
|
||||
<a name="TX2.metric"></a>
|
||||
|
||||
### TX2.metric(name, [function]) ⇒ [<code>Metric</code>](#Metric)
|
||||
Expose a Metric
|
||||
|
||||
**Kind**: static method of [<code>TX2</code>](#TX2)
|
||||
**Returns**: [<code>Metric</code>](#Metric) - A metrics object
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| name | <code>string</code> | Name of the metric |
|
||||
| [function] | <code>function</code> | Optional function to trigger every second to retrieve updated value |
|
||||
|
||||
**Example**
|
||||
```js
|
||||
tx2.metric('metric_name', () => obj.value)
|
||||
```
|
||||
**Example**
|
||||
```js
|
||||
tx2.metric('metric_name', 'unit', () => obj.value)
|
||||
```
|
||||
**Example**
|
||||
```js
|
||||
let mn = tx2.metric('metric_name')
|
||||
mn.set(20)
|
||||
```
|
||||
<a name="TX2.counter"></a>
|
||||
|
||||
### TX2.counter(name) ⇒ [<code>Counter</code>](#Counter)
|
||||
Expose a Metric of type: Counter. By calling .inc() or .dec() you update that value
|
||||
|
||||
**Kind**: static method of [<code>TX2</code>](#TX2)
|
||||
|
||||
| Param | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| name | <code>string</code> | Name of the Metric |
|
||||
|
||||
<a name="Metric"></a>
|
||||
|
||||
## Metric : <code>Object</code>
|
||||
**Kind**: global typedef
|
||||
**Properties**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| val | <code>function</code> | Return the current value |
|
||||
| set | <code>function</code> | Set value |
|
||||
|
||||
<a name="Counter"></a>
|
||||
|
||||
## Counter : <code>object</code>
|
||||
Expose a metric of type: Counter.
|
||||
|
||||
**Kind**: global typedef
|
||||
**Properties**
|
||||
|
||||
| Name | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| inc | <code>function</code> | Increment value |
|
||||
| dev | <code>function</code> | Decrement value |
|
||||
|
||||
21
api.hyungi.net/node_modules/tx2/LICENSE
generated
vendored
Normal file
21
api.hyungi.net/node_modules/tx2/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2077 PM2
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
44
api.hyungi.net/node_modules/tx2/README.md
generated
vendored
Normal file
44
api.hyungi.net/node_modules/tx2/README.md
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
## tx2
|
||||
|
||||
Report Events, Metrics, Issues, Actions to PM2 and PM2.io.
|
||||
|
||||
```javascript
|
||||
const tx2 = require('tx2')
|
||||
|
||||
let body = { calories : 20 }
|
||||
tx2.metric('burnt calories', () => body.calories)
|
||||
|
||||
tx2.action('lift weights', (cb) => {
|
||||
cb({ success: true })
|
||||
})
|
||||
```
|
||||
|
||||
Check [API.md](API.md) for full API doc.
|
||||
|
||||
Once you have created some metrics:
|
||||
|
||||
```bash
|
||||
$ pm2 start app.js
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```bash
|
||||
# Inspect primitive reported
|
||||
$ pm2 show app
|
||||
```
|
||||
|
||||
or go to pm2.io for web based interface + insights creation.
|
||||
|
||||
## More
|
||||
|
||||
Generate documentation:
|
||||
|
||||
```bash
|
||||
$ npm run doc
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
41
api.hyungi.net/node_modules/tx2/example/events.js
generated
vendored
Normal file
41
api.hyungi.net/node_modules/tx2/example/events.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
const tx2 = require('..')
|
||||
|
||||
console.log(tx2)
|
||||
|
||||
tx2.emit('test', { data: 'yes' })
|
||||
|
||||
// Metrics variants
|
||||
tx2.metric({
|
||||
name: 'test',
|
||||
val: () => {
|
||||
return 20
|
||||
}
|
||||
})
|
||||
|
||||
tx2.metric('test2', () => {
|
||||
return 30
|
||||
})
|
||||
|
||||
let m = tx2.metric('test3', 0)
|
||||
|
||||
m.set(45)
|
||||
|
||||
// Histogram
|
||||
|
||||
let n = tx2.histogram({
|
||||
name: 'histo1',
|
||||
val: () => {
|
||||
return Math.random()
|
||||
}
|
||||
})
|
||||
|
||||
// OR
|
||||
n.update(Math.random() * 1000)
|
||||
|
||||
tx2.action('toto', (cb) => {
|
||||
return cb({yessai:true})
|
||||
})
|
||||
|
||||
|
||||
setInterval(() => {} , 1000)
|
||||
4
api.hyungi.net/node_modules/tx2/index.js
generated
vendored
Normal file
4
api.hyungi.net/node_modules/tx2/index.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
const PX2 = require('./src/')
|
||||
|
||||
module.exports = new PX2()
|
||||
20
api.hyungi.net/node_modules/tx2/package.json
generated
vendored
Normal file
20
api.hyungi.net/node_modules/tx2/package.json
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "tx2",
|
||||
"version": "1.0.5",
|
||||
"description": "Metrics, Issues, Actions, Events reporting library",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha test/*.mocha.js",
|
||||
"doc": "npx jsdoc2md src/* > API.md"
|
||||
},
|
||||
"author": "PM2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-stringify-safe": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jsdoc-to-markdown": "^6.0.1",
|
||||
"mocha": "8",
|
||||
"should": "13"
|
||||
}
|
||||
}
|
||||
84
api.hyungi.net/node_modules/tx2/src/actions.js
generated
vendored
Normal file
84
api.hyungi.net/node_modules/tx2/src/actions.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Expose an action/function triggerable via PM2 or PM2.io
|
||||
* @memberof TX2
|
||||
* @param {string} action_name Name of the action
|
||||
* @param {object} [opts] Optional parameter
|
||||
* @param {function} fn Function to be called
|
||||
*
|
||||
* @example <caption>Action without arguments</caption>
|
||||
* tx2.action('run_query', (cb) => {
|
||||
* cb({ success: true })
|
||||
* })
|
||||
* @example <caption>Action with arguments</caption>
|
||||
* tx2.action('run_query', arg1, (cb) => {
|
||||
* cb({ success: arg1 })
|
||||
* })
|
||||
*/
|
||||
action(action_name, opts, fn) {
|
||||
if (!fn) {
|
||||
fn = opts
|
||||
opts = null
|
||||
}
|
||||
|
||||
if (!action_name)
|
||||
return console.error('[PMX] action.action_name is missing')
|
||||
if (!fn)
|
||||
return console.error('[PMX] emit.data is mission')
|
||||
|
||||
// Notify the action
|
||||
this.send({
|
||||
type : 'axm:action',
|
||||
data : {
|
||||
action_name : action_name,
|
||||
opts : opts,
|
||||
arity : fn.length
|
||||
}
|
||||
})
|
||||
|
||||
let reply = (data) => {
|
||||
if (data.length) {
|
||||
data._length = data.length
|
||||
delete data.length
|
||||
}
|
||||
|
||||
this.send({
|
||||
type : 'axm:reply',
|
||||
data : {
|
||||
return : data,
|
||||
action_name : action_name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
process.on('message', (data) => {
|
||||
if (!data) return false
|
||||
|
||||
// Notify the action
|
||||
if (data && (data == action_name || data.msg == action_name))
|
||||
this.event('action triggered', { action_name, opts })
|
||||
|
||||
// In case 2 arguments has been set but no options has been transmitted
|
||||
if (fn.length === 2 && typeof(data) === 'string' && data === action_name)
|
||||
return fn({}, reply)
|
||||
|
||||
// In case 1 arguments has been set but options has been transmitted
|
||||
if (fn.length === 1 && typeof(data) === 'object' && data.msg === action_name)
|
||||
return fn(reply)
|
||||
|
||||
/**
|
||||
* Classical call
|
||||
*/
|
||||
if (typeof(data) === 'string' && data === action_name)
|
||||
return fn(reply)
|
||||
|
||||
/**
|
||||
* If data is an object == v2 protocol
|
||||
* Pass the opts as first argument
|
||||
*/
|
||||
if (typeof(data) === 'object' && data.msg === action_name)
|
||||
return fn(data.opts, reply)
|
||||
})
|
||||
}
|
||||
}
|
||||
33
api.hyungi.net/node_modules/tx2/src/events.js
generated
vendored
Normal file
33
api.hyungi.net/node_modules/tx2/src/events.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
const stringify = require('json-stringify-safe')
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Sends an Event
|
||||
* @memberof TX2
|
||||
* @param {string} name Name of the event
|
||||
* @param {object} data Metadata attached to the event
|
||||
* @example
|
||||
* tx2.event('event-name', { multi: 'data' })
|
||||
*/
|
||||
event(name, data) {
|
||||
if (!name)
|
||||
return console.error('[AXM] emit.name is missing')
|
||||
|
||||
let inflight_obj = {}
|
||||
|
||||
if (typeof(data) == 'object')
|
||||
inflight_obj = JSON.parse(stringify(data))
|
||||
else {
|
||||
inflight_obj.data = data || null
|
||||
}
|
||||
|
||||
inflight_obj.__name = name
|
||||
|
||||
this.send({
|
||||
type : 'human:event',
|
||||
data : inflight_obj
|
||||
})
|
||||
}
|
||||
}
|
||||
58
api.hyungi.net/node_modules/tx2/src/index.js
generated
vendored
Normal file
58
api.hyungi.net/node_modules/tx2/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
const Events = require('./events.js')
|
||||
const Actions = require('./actions.js')
|
||||
const Metrics = require('./metrics.js')
|
||||
const Issues = require('./issues.js')
|
||||
|
||||
const EventEmitter = require('events')
|
||||
|
||||
const stringify = require('json-stringify-safe')
|
||||
|
||||
/**
|
||||
* @namespace TX2
|
||||
* @class TX2
|
||||
*/
|
||||
class TX2 extends EventEmitter {
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
Object.assign(this, Events)
|
||||
Object.assign(this, Actions)
|
||||
Object.assign(this, Metrics)
|
||||
Object.assign(this, Issues)
|
||||
|
||||
var p_interval = setInterval(() => {
|
||||
this.send({
|
||||
type : 'axm:monitor',
|
||||
data : Metrics.prepareData()
|
||||
})
|
||||
}, 990)
|
||||
|
||||
p_interval.unref()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send JSON to PM2
|
||||
* @private
|
||||
* @param {object} args
|
||||
*/
|
||||
send(args) {
|
||||
this.emit('data', args)
|
||||
if (!process.send) {
|
||||
var output = args.data
|
||||
delete output.__name
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
process.send(JSON.parse(stringify(args)))
|
||||
} catch(e) {
|
||||
console.error('Process disconnected from parent !')
|
||||
console.error(e.stack || e)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TX2
|
||||
62
api.hyungi.net/node_modules/tx2/src/issues.js
generated
vendored
Normal file
62
api.hyungi.net/node_modules/tx2/src/issues.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
const jsonize = function(err, filter, space) {
|
||||
if (typeof(err) != 'object')
|
||||
return err
|
||||
|
||||
var plainObject = {}
|
||||
|
||||
Object.getOwnPropertyNames(err).forEach(function(key) {
|
||||
plainObject[key] = err[key]
|
||||
})
|
||||
return plainObject
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
_interpretError: function(err) {
|
||||
var s_err = {}
|
||||
|
||||
if (typeof(err) === 'string') {
|
||||
// Simple string processing
|
||||
s_err.message = err
|
||||
s_err.stack = err
|
||||
}
|
||||
else if (!(err instanceof Error) && typeof(err) === 'object') {
|
||||
// JSON processing
|
||||
s_err.message = err
|
||||
s_err.stack = err
|
||||
}
|
||||
else if (err instanceof Error) {
|
||||
// Error object type processing
|
||||
err.stack
|
||||
if (err.__error_callsites) {
|
||||
var stackFrames = []
|
||||
err.__error_callsites.forEach(function(callSite) {
|
||||
stackFrames.push({ file_name: callSite.getFileName(), line_number: callSite.getLineNumber()})
|
||||
})
|
||||
err.stackframes = stackFrames
|
||||
delete err.__error_callsites
|
||||
}
|
||||
s_err = err
|
||||
}
|
||||
|
||||
return jsonize(s_err)
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends an Issue
|
||||
* @memberof TX2
|
||||
* @param {string|Error} err Error object or string to notify
|
||||
* @example
|
||||
* tx2.issue(new Error('bad error')
|
||||
*/
|
||||
issue: function(err) {
|
||||
var ret_err = this._interpretError(err)
|
||||
|
||||
this.send({
|
||||
type : 'process:exception',
|
||||
data : ret_err
|
||||
})
|
||||
|
||||
return ret_err
|
||||
}
|
||||
}
|
||||
240
api.hyungi.net/node_modules/tx2/src/metrics.js
generated
vendored
Normal file
240
api.hyungi.net/node_modules/tx2/src/metrics.js
generated
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
|
||||
var Counter = require('./utils/probes/Counter.js')
|
||||
var Histogram = require('./utils/probes/Histogram.js')
|
||||
var Meter = require('./utils/probes/Meter.js')
|
||||
|
||||
function getValue(value) {
|
||||
if (typeof(value) == 'function')
|
||||
return value()
|
||||
return value
|
||||
}
|
||||
|
||||
const DEFAULT_AGGREGATION = 'avg'
|
||||
const AVAILABLE_AGG_TYPES = ['avg', 'min', 'max', 'sum', 'none']
|
||||
const AVAILABLE_MEASUREMENTS = ['min', 'max','sum','count','variance','mean','stddev','median','p75','p95','p99','p999']
|
||||
|
||||
module.exports = {
|
||||
_metrics: {},
|
||||
prepareData: function() {
|
||||
var cooked_data = {}
|
||||
|
||||
Object.keys(this._metrics).forEach((probe_name) => {
|
||||
|
||||
if (typeof(this._metrics[probe_name].value) == 'undefined')
|
||||
return false
|
||||
|
||||
cooked_data[probe_name] = {
|
||||
value: getValue(this._metrics[probe_name].value)
|
||||
}
|
||||
|
||||
if (this._metrics[probe_name].unit)
|
||||
cooked_data[probe_name].unit = this._metrics[probe_name].unit
|
||||
|
||||
/**
|
||||
* Attach aggregation mode
|
||||
*/
|
||||
if (this._metrics[probe_name].agg_type &&
|
||||
this._metrics[probe_name].agg_type != 'none')
|
||||
cooked_data[probe_name].agg_type = this._metrics[probe_name].agg_type
|
||||
|
||||
if (this._metrics[probe_name].unit)
|
||||
cooked_data[probe_name].unit = this._metrics[probe_name].unit
|
||||
})
|
||||
return cooked_data
|
||||
},
|
||||
|
||||
/**
|
||||
* This reflect data to keymetrics
|
||||
* pmx.transpose('prop name', fn)
|
||||
*
|
||||
* or
|
||||
*
|
||||
* pmx.transpose({
|
||||
* name : 'variable name',
|
||||
* data : function() { return value }
|
||||
* })
|
||||
*/
|
||||
transpose : function(variable_name, reporter) {
|
||||
if (typeof variable_name === 'object') {
|
||||
reporter = variable_name.data
|
||||
variable_name = variable_name.name
|
||||
}
|
||||
|
||||
if (typeof reporter !== 'function') {
|
||||
return console.error('[PMX] reporter is not a function')
|
||||
}
|
||||
|
||||
this._metrics[variable_name] = {
|
||||
value: reporter
|
||||
}
|
||||
},
|
||||
metricExists: function(metric_name) {
|
||||
return !!this._metrics[metric_name]
|
||||
},
|
||||
|
||||
/**
|
||||
* @typedef {Object} Metric
|
||||
* @property {function} val Return the current value
|
||||
* @property {function} set Set value
|
||||
*/
|
||||
|
||||
/**
|
||||
* Expose a Metric
|
||||
* @memberof TX2
|
||||
* @param {string} name Name of the metric
|
||||
* @param {function} [function] Optional function to trigger every second to retrieve updated value
|
||||
* @returns {Metric} A metrics object
|
||||
* @example
|
||||
* tx2.metric('metric_name', () => obj.value)
|
||||
* @example
|
||||
* tx2.metric('metric_name', 'unit', () => obj.value)
|
||||
* @example
|
||||
* let mn = tx2.metric('metric_name')
|
||||
* mn.set(20)
|
||||
*/
|
||||
metric : function(opts, unit, val) {
|
||||
let name, value
|
||||
|
||||
// tx2.metric('metric-name', 'unit', () => variable)
|
||||
if (typeof(opts) == 'string' && typeof(unit) == 'string') {
|
||||
name = opts
|
||||
unit = unit
|
||||
value = val
|
||||
}
|
||||
else if (typeof(opts) == 'string' && typeof(unit) == 'function') {
|
||||
name = opts
|
||||
value = unit
|
||||
}
|
||||
else if (typeof(opts) == 'string' && typeof(unit) == 'number') {
|
||||
name = opts
|
||||
value = unit
|
||||
}
|
||||
else if (typeof(opts) === 'object') {
|
||||
name = opts.name
|
||||
value = opts.val || opts.value
|
||||
unit = opts.unit || null
|
||||
}
|
||||
|
||||
if (!name)
|
||||
return console.error('[PX2][Metric] Name not defined')
|
||||
|
||||
this._metrics[name] = {
|
||||
value: value,
|
||||
unit: unit
|
||||
}
|
||||
|
||||
return {
|
||||
val : () => {
|
||||
var value = this._metrics[name].value
|
||||
|
||||
if (typeof(value) == 'function')
|
||||
value = value()
|
||||
|
||||
return value
|
||||
},
|
||||
set : (dt) => {
|
||||
this._metrics[name].value = dt
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Expose a Metric of type Histogram. This computes a value accross based on the measurement option and will return a value accordingly
|
||||
@private
|
||||
* @memberof TX2
|
||||
* @param {string} [opts.name] Metric Name
|
||||
* @param {string} [opts.measurement] Measurement made on time period, can be 'min', 'max','sum','count','variance','mean','stddev','median','p75','p95','p99','p999'
|
||||
* @param {function} [opts.value] Function to call to retrieve new value every second
|
||||
* @returns {}
|
||||
*/
|
||||
histogram : function(opts) {
|
||||
if (!opts.name)
|
||||
return console.error('[Metric][Histogram] Name not defined')
|
||||
|
||||
opts.measurement = opts.measurement || 'mean'
|
||||
opts.unit = opts.unit || ''
|
||||
|
||||
if (AVAILABLE_MEASUREMENTS.indexOf(opts.measurement) == -1)
|
||||
return console.error('[Metric][Histogram] Measure type %s does not exists', opts.measurement)
|
||||
|
||||
var histogram = new Histogram(opts)
|
||||
|
||||
this._metrics[opts.name] = {
|
||||
value: () => {
|
||||
|
||||
if (opts.val || opts.value) {
|
||||
var value = opts.val || opts.value
|
||||
if (typeof(value) == 'function')
|
||||
value = value()
|
||||
histogram.update(value)
|
||||
}
|
||||
|
||||
return (Math.round(histogram.val() * 100) / 100)
|
||||
},
|
||||
unit : opts.unit
|
||||
}
|
||||
|
||||
return histogram
|
||||
},
|
||||
|
||||
/**
|
||||
* Expose a Metric of type: Meter. This (???)
|
||||
* @private
|
||||
* @param {string} opts.name Name of the Metric
|
||||
* @returns {}
|
||||
*/
|
||||
meter : function(opts) {
|
||||
if (!opts.name)
|
||||
return console.error('[Metric][Meter] Name not defined')
|
||||
|
||||
opts.unit = opts.unit || ''
|
||||
|
||||
var meter = new Meter(opts)
|
||||
|
||||
this._metrics[opts.name] = {
|
||||
value: function() {
|
||||
return meter.val() + '' + opts.unit
|
||||
},
|
||||
unit : opts.unit
|
||||
}
|
||||
|
||||
return meter
|
||||
},
|
||||
|
||||
/**
|
||||
* Expose a metric of type: Counter.
|
||||
* @typedef {object} Counter
|
||||
* @property {function} inc Increment value
|
||||
* @property {function} dev Decrement value
|
||||
*/
|
||||
|
||||
/**
|
||||
* Expose a Metric of type: Counter. By calling .inc() or .dec() you update that value
|
||||
* @memberof TX2
|
||||
* @param {string} name Name of the Metric
|
||||
* @returns {Counter}
|
||||
*/
|
||||
counter : function(opts) {
|
||||
let name, unit, agg_type = DEFAULT_AGGREGATION
|
||||
|
||||
if (typeof(opts) == 'string')
|
||||
name = opts
|
||||
else {
|
||||
name = opts.name
|
||||
unit = opts.unit
|
||||
}
|
||||
|
||||
if (!name)
|
||||
return console.error('[Metric][Counter] Name not defined')
|
||||
|
||||
var counter = new Counter()
|
||||
|
||||
this._metrics[name] = {
|
||||
value: function() { return counter.val() },
|
||||
agg_type: agg_type,
|
||||
unit : unit || null
|
||||
}
|
||||
|
||||
return counter
|
||||
}
|
||||
}
|
||||
132
api.hyungi.net/node_modules/tx2/src/utils/probes/BinaryHeap.js
generated
vendored
Normal file
132
api.hyungi.net/node_modules/tx2/src/utils/probes/BinaryHeap.js
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
// Based on http://en.wikipedia.org/wiki/Binary_Heap
|
||||
// as well as http://eloquentjavascript.net/appendix2.html
|
||||
module.exports = BinaryHeap;
|
||||
function BinaryHeap(options) {
|
||||
options = options || {};
|
||||
|
||||
this._elements = options.elements || [];
|
||||
this._score = options.score || this._score;
|
||||
}
|
||||
|
||||
BinaryHeap.prototype.add = function(/* elements */) {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var element = arguments[i];
|
||||
|
||||
this._elements.push(element);
|
||||
this._bubble(this._elements.length - 1);
|
||||
}
|
||||
};
|
||||
|
||||
BinaryHeap.prototype.first = function() {
|
||||
return this._elements[0];
|
||||
};
|
||||
|
||||
BinaryHeap.prototype.removeFirst = function() {
|
||||
var root = this._elements[0];
|
||||
var last = this._elements.pop();
|
||||
|
||||
if (this._elements.length > 0) {
|
||||
this._elements[0] = last;
|
||||
this._sink(0);
|
||||
}
|
||||
|
||||
return root;
|
||||
};
|
||||
|
||||
BinaryHeap.prototype.clone = function() {
|
||||
return new BinaryHeap({
|
||||
elements: this.toArray(),
|
||||
score: this._score,
|
||||
});
|
||||
};
|
||||
|
||||
BinaryHeap.prototype.toSortedArray = function() {
|
||||
var array = [];
|
||||
var clone = this.clone();
|
||||
|
||||
while (true) {
|
||||
var element = clone.removeFirst();
|
||||
if (element === undefined) break;
|
||||
|
||||
array.push(element);
|
||||
}
|
||||
|
||||
return array;
|
||||
};
|
||||
|
||||
BinaryHeap.prototype.toArray = function() {
|
||||
return [].concat(this._elements);
|
||||
};
|
||||
|
||||
BinaryHeap.prototype.size = function() {
|
||||
return this._elements.length;
|
||||
};
|
||||
|
||||
BinaryHeap.prototype._bubble = function(bubbleIndex) {
|
||||
var bubbleElement = this._elements[bubbleIndex];
|
||||
var bubbleScore = this._score(bubbleElement);
|
||||
|
||||
while (bubbleIndex > 0) {
|
||||
var parentIndex = this._parentIndex(bubbleIndex);
|
||||
var parentElement = this._elements[parentIndex];
|
||||
var parentScore = this._score(parentElement);
|
||||
|
||||
if (bubbleScore <= parentScore) break;
|
||||
|
||||
this._elements[parentIndex] = bubbleElement;
|
||||
this._elements[bubbleIndex] = parentElement;
|
||||
bubbleIndex = parentIndex;
|
||||
}
|
||||
};
|
||||
|
||||
BinaryHeap.prototype._sink = function(sinkIndex) {
|
||||
var sinkElement = this._elements[sinkIndex];
|
||||
var sinkScore = this._score(sinkElement);
|
||||
var length = this._elements.length;
|
||||
|
||||
while (true) {
|
||||
var swapIndex = null;
|
||||
var swapScore = null;
|
||||
var swapElement = null;
|
||||
var childIndexes = this._childIndexes(sinkIndex);
|
||||
|
||||
for (var i = 0; i < childIndexes.length; i++) {
|
||||
var childIndex = childIndexes[i];
|
||||
|
||||
if (childIndex >= length) break;
|
||||
|
||||
var childElement = this._elements[childIndex];
|
||||
var childScore = this._score(childElement);
|
||||
|
||||
if (childScore > sinkScore) {
|
||||
if (swapScore === null || swapScore < childScore) {
|
||||
swapIndex = childIndex;
|
||||
swapScore = childScore;
|
||||
swapElement = childElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (swapIndex === null) break;
|
||||
|
||||
this._elements[swapIndex] = sinkElement;
|
||||
this._elements[sinkIndex] = swapElement;
|
||||
sinkIndex = swapIndex;
|
||||
}
|
||||
};
|
||||
|
||||
BinaryHeap.prototype._parentIndex = function(index) {
|
||||
return Math.floor((index - 1) / 2);
|
||||
};
|
||||
|
||||
BinaryHeap.prototype._childIndexes = function(index) {
|
||||
return [
|
||||
2 * index + 1,
|
||||
2 * index + 2,
|
||||
];
|
||||
return ;
|
||||
};
|
||||
|
||||
BinaryHeap.prototype._score = function(element) {
|
||||
return element.valueOf();
|
||||
};
|
||||
26
api.hyungi.net/node_modules/tx2/src/utils/probes/Counter.js
generated
vendored
Normal file
26
api.hyungi.net/node_modules/tx2/src/utils/probes/Counter.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
module.exports = Counter;
|
||||
|
||||
function Counter(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
this._count = opts.count || 0;
|
||||
}
|
||||
|
||||
Counter.prototype.val = function() {
|
||||
return this._count;
|
||||
};
|
||||
|
||||
Counter.prototype.inc = function(n) {
|
||||
const incBy = n == null ? 1 : n
|
||||
this._count += incBy;
|
||||
};
|
||||
|
||||
Counter.prototype.dec = function(n) {
|
||||
const decBy = n == null ? 1 : n
|
||||
this._count -= decBy;
|
||||
};
|
||||
|
||||
Counter.prototype.reset = function(count) {
|
||||
this._count = count || 0;
|
||||
};
|
||||
110
api.hyungi.net/node_modules/tx2/src/utils/probes/EDS.js
generated
vendored
Normal file
110
api.hyungi.net/node_modules/tx2/src/utils/probes/EDS.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
var BinaryHeap = require('./BinaryHeap');
|
||||
var units = require('./units');
|
||||
|
||||
module.exports = ExponentiallyDecayingSample;
|
||||
function ExponentiallyDecayingSample(options) {
|
||||
options = options || {};
|
||||
|
||||
this._elements = new BinaryHeap({
|
||||
score: function(element) {
|
||||
return -element.priority;
|
||||
}
|
||||
});
|
||||
|
||||
this._rescaleInterval = options.rescaleInterval || ExponentiallyDecayingSample.RESCALE_INTERVAL;
|
||||
this._alpha = options.alpha || ExponentiallyDecayingSample.ALPHA;
|
||||
this._size = options.size || ExponentiallyDecayingSample.SIZE;
|
||||
this._random = options.random || this._random;
|
||||
this._landmark = null;
|
||||
this._nextRescale = null;
|
||||
this._mean = null;
|
||||
}
|
||||
|
||||
ExponentiallyDecayingSample.RESCALE_INTERVAL = 1 * units.HOURS;
|
||||
ExponentiallyDecayingSample.ALPHA = 0.015;
|
||||
ExponentiallyDecayingSample.SIZE = 1028;
|
||||
|
||||
ExponentiallyDecayingSample.prototype.update = function(value, timestamp) {
|
||||
var now = Date.now();
|
||||
if (!this._landmark) {
|
||||
this._landmark = now;
|
||||
this._nextRescale = this._landmark + this._rescaleInterval;
|
||||
}
|
||||
|
||||
timestamp = timestamp || now;
|
||||
|
||||
var newSize = this._elements.size() + 1;
|
||||
|
||||
var element = {
|
||||
priority: this._priority(timestamp - this._landmark),
|
||||
value: value
|
||||
};
|
||||
|
||||
if (newSize <= this._size) {
|
||||
this._elements.add(element);
|
||||
} else if (element.priority > this._elements.first().priority) {
|
||||
this._elements.removeFirst();
|
||||
this._elements.add(element);
|
||||
}
|
||||
|
||||
if (now >= this._nextRescale) this._rescale(now);
|
||||
};
|
||||
|
||||
ExponentiallyDecayingSample.prototype.toSortedArray = function() {
|
||||
return this._elements
|
||||
.toSortedArray()
|
||||
.map(function(element) {
|
||||
return element.value;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
ExponentiallyDecayingSample.prototype.toArray = function() {
|
||||
return this._elements
|
||||
.toArray()
|
||||
.map(function(element) {
|
||||
return element.value;
|
||||
});
|
||||
};
|
||||
|
||||
ExponentiallyDecayingSample.prototype._weight = function(age) {
|
||||
// We divide by 1000 to not run into huge numbers before reaching a
|
||||
// rescale event.
|
||||
return Math.exp(this._alpha * (age / 1000));
|
||||
};
|
||||
|
||||
ExponentiallyDecayingSample.prototype._priority = function(age) {
|
||||
return this._weight(age) / this._random();
|
||||
};
|
||||
|
||||
ExponentiallyDecayingSample.prototype._random = function() {
|
||||
return Math.random();
|
||||
};
|
||||
|
||||
ExponentiallyDecayingSample.prototype._rescale = function(now) {
|
||||
now = now || Date.now();
|
||||
|
||||
var self = this;
|
||||
var oldLandmark = this._landmark;
|
||||
this._landmark = now || Date.now();
|
||||
this._nextRescale = now + this._rescaleInterval;
|
||||
|
||||
var factor = self._priority(-(self._landmark - oldLandmark));
|
||||
|
||||
this._elements
|
||||
.toArray()
|
||||
.forEach(function(element) {
|
||||
element.priority *= factor;
|
||||
});
|
||||
};
|
||||
|
||||
ExponentiallyDecayingSample.prototype.avg = function(now) {
|
||||
var sum = 0;
|
||||
this._elements
|
||||
.toArray()
|
||||
.forEach(function(element) {
|
||||
sum += element.value;
|
||||
});
|
||||
return (sum / this._elements.size());
|
||||
}
|
||||
29
api.hyungi.net/node_modules/tx2/src/utils/probes/EWMA.js
generated
vendored
Normal file
29
api.hyungi.net/node_modules/tx2/src/utils/probes/EWMA.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
var units = require('./units');
|
||||
|
||||
module.exports = ExponentiallyWeightedMovingAverage;
|
||||
|
||||
function ExponentiallyWeightedMovingAverage(timePeriod, tickInterval) {
|
||||
this._timePeriod = timePeriod || 1 * units.MINUTE;
|
||||
this._tickInterval = tickInterval || ExponentiallyWeightedMovingAverage.TICK_INTERVAL;
|
||||
this._alpha = 1 - Math.exp(-this._tickInterval / this._timePeriod);
|
||||
this._count = 0;
|
||||
this._rate = 0;
|
||||
};
|
||||
|
||||
ExponentiallyWeightedMovingAverage.TICK_INTERVAL = 5 * units.SECONDS;
|
||||
|
||||
ExponentiallyWeightedMovingAverage.prototype.update = function(n) {
|
||||
this._count += n;
|
||||
};
|
||||
|
||||
ExponentiallyWeightedMovingAverage.prototype.tick = function() {
|
||||
var instantRate = this._count / this._tickInterval;
|
||||
this._count = 0;
|
||||
|
||||
this._rate += (this._alpha * (instantRate - this._rate));
|
||||
};
|
||||
|
||||
ExponentiallyWeightedMovingAverage.prototype.rate = function(timeUnit) {
|
||||
return (this._rate || 0) * timeUnit;
|
||||
};
|
||||
196
api.hyungi.net/node_modules/tx2/src/utils/probes/Histogram.js
generated
vendored
Normal file
196
api.hyungi.net/node_modules/tx2/src/utils/probes/Histogram.js
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
|
||||
var EDS = require('./EDS.js');
|
||||
|
||||
function Histogram(opts) {
|
||||
var self = this;
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
this._measurement = opts.measurement;
|
||||
this._call_fn = null;
|
||||
|
||||
var methods = {
|
||||
min : this.getMin,
|
||||
max : this.getMax,
|
||||
sum : this.getSum,
|
||||
count : this.getCount,
|
||||
variance : this._calculateVariance,
|
||||
mean : this._calculateMean,
|
||||
stddev : this._calculateStddev,
|
||||
ema : this.getEma()
|
||||
};
|
||||
|
||||
if (methods[this._measurement])
|
||||
this._call_fn = methods[this._measurement];
|
||||
else {
|
||||
this._call_fn = function() {
|
||||
var percentiles = this.percentiles([0.5, 0.75, 0.95, 0.99, 0.999]);
|
||||
|
||||
var medians = {
|
||||
median : percentiles[0.5],
|
||||
p75 : percentiles[0.75],
|
||||
p95 : percentiles[0.95],
|
||||
p99 : percentiles[0.99],
|
||||
p999 : percentiles[0.999]
|
||||
};
|
||||
|
||||
return medians[this._measurement];
|
||||
}
|
||||
}
|
||||
this._sample = new EDS();
|
||||
this._min = null;
|
||||
this._max = null;
|
||||
this._count = 0;
|
||||
this._sum = 0;
|
||||
|
||||
// These are for the Welford algorithm for calculating running variance
|
||||
// without floating-point doom.
|
||||
this._varianceM = 0;
|
||||
this._varianceS = 0;
|
||||
this._ema = 0;
|
||||
}
|
||||
|
||||
Histogram.prototype.update = function(value) {
|
||||
this._count++;
|
||||
this._sum += value;
|
||||
|
||||
this._sample.update(value);
|
||||
this._updateMin(value);
|
||||
this._updateMax(value);
|
||||
this._updateVariance(value);
|
||||
this._updateEma(value);
|
||||
};
|
||||
|
||||
Histogram.prototype.percentiles = function(percentiles) {
|
||||
var values = this._sample
|
||||
.toArray()
|
||||
.sort(function(a, b) {
|
||||
return (a === b)
|
||||
? 0
|
||||
: a - b;
|
||||
});
|
||||
|
||||
var results = {};
|
||||
|
||||
for (var i = 0; i < percentiles.length; i++) {
|
||||
var percentile = percentiles[i];
|
||||
if (!values.length) {
|
||||
results[percentile] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
var pos = percentile * (values.length + 1);
|
||||
|
||||
if (pos < 1) {
|
||||
results[percentile] = values[0];
|
||||
} else if (pos >= values.length) {
|
||||
results[percentile] = values[values.length - 1];
|
||||
} else {
|
||||
var lower = values[Math.floor(pos) - 1];
|
||||
var upper = values[Math.ceil(pos) - 1];
|
||||
|
||||
results[percentile] = lower + (pos - Math.floor(pos)) * (upper - lower);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
Histogram.prototype.reset = function() {
|
||||
this.constructor.call(this);
|
||||
};
|
||||
|
||||
Histogram.prototype.val = function() {
|
||||
if (typeof(this._call_fn) === 'function')
|
||||
return this._call_fn();
|
||||
else
|
||||
return this._call_fn;
|
||||
};
|
||||
|
||||
Histogram.prototype.getMin = function() {
|
||||
return this._min;
|
||||
};
|
||||
|
||||
Histogram.prototype.getMax = function() {
|
||||
return this._max;
|
||||
};
|
||||
|
||||
Histogram.prototype.getSum = function() {
|
||||
return this._sum;
|
||||
};
|
||||
|
||||
Histogram.prototype.getCount = function() {
|
||||
return this._count;
|
||||
};
|
||||
|
||||
Histogram.prototype.getEma = function() {
|
||||
return this._ema;
|
||||
}
|
||||
|
||||
Histogram.prototype.fullResults = function() {
|
||||
var percentiles = this.percentiles([0.5, 0.75, 0.95, 0.99, 0.999]);
|
||||
|
||||
return {
|
||||
min : this._min,
|
||||
max : this._max,
|
||||
sum : this._sum,
|
||||
variance : this._calculateVariance(),
|
||||
mean : this._calculateMean(),
|
||||
stddev : this._calculateStddev(),
|
||||
count : this._count,
|
||||
median : percentiles[0.5],
|
||||
p75 : percentiles[0.75],
|
||||
p95 : percentiles[0.95],
|
||||
p99 : percentiles[0.99],
|
||||
p999 : percentiles[0.999],
|
||||
ema : this._ema
|
||||
};
|
||||
};
|
||||
|
||||
Histogram.prototype._updateMin = function(value) {
|
||||
if (this._min === null || value < this._min) {
|
||||
this._min = value;
|
||||
//console.log(value);
|
||||
}
|
||||
};
|
||||
|
||||
Histogram.prototype._updateMax = function(value) {
|
||||
if (this._max === null || value > this._max) {
|
||||
this._max = value;
|
||||
}
|
||||
};
|
||||
|
||||
Histogram.prototype._updateVariance = function(value) {
|
||||
if (this._count === 1) return this._varianceM = value;
|
||||
|
||||
var oldM = this._varianceM;
|
||||
|
||||
this._varianceM += ((value - oldM) / this._count);
|
||||
this._varianceS += ((value - oldM) * (value - this._varianceM));
|
||||
};
|
||||
|
||||
Histogram.prototype._updateEma = function(value) {
|
||||
if (this._count <= 1) return this._ema = this._calculateMean();
|
||||
var alpha = 2 / (1 + this._count);
|
||||
this._ema = value * alpha + this._ema * (1 - alpha);
|
||||
}
|
||||
|
||||
Histogram.prototype._calculateMean = function() {
|
||||
return (this._count === 0)
|
||||
? 0
|
||||
: this._sum / this._count;
|
||||
};
|
||||
|
||||
Histogram.prototype._calculateVariance = function() {
|
||||
return (this._count <= 1)
|
||||
? null
|
||||
: this._varianceS / (this._count - 1);
|
||||
};
|
||||
|
||||
Histogram.prototype._calculateStddev = function() {
|
||||
return (this._count < 1)
|
||||
? null
|
||||
: Math.sqrt(this._calculateVariance());
|
||||
};
|
||||
|
||||
module.exports = Histogram;
|
||||
33
api.hyungi.net/node_modules/tx2/src/utils/probes/Meter.js
generated
vendored
Normal file
33
api.hyungi.net/node_modules/tx2/src/utils/probes/Meter.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
var units = require('./units')
|
||||
var EWMA = require('./EWMA')
|
||||
|
||||
function Meter(opts) {
|
||||
var self = this
|
||||
|
||||
this._tickInterval = units.SECONDS
|
||||
this._samples = opts.seconds || 1
|
||||
this._timeframe = opts.timeframe || 60
|
||||
|
||||
this._rate = new EWMA(units.SECONDS, this._tickInterval)
|
||||
|
||||
this._interval = setInterval(function() {
|
||||
self._rate.tick()
|
||||
}, this._tickInterval)
|
||||
|
||||
this._interval.unref()
|
||||
}
|
||||
|
||||
Meter.RATE_UNIT = units.SECONDS
|
||||
|
||||
Meter.prototype.mark = function(n) {
|
||||
n = n || 1
|
||||
|
||||
this._rate.update(n)
|
||||
}
|
||||
|
||||
Meter.prototype.val = function() {
|
||||
return Math.round(this._rate.rate(Meter.RATE_UNIT) * 100 ) / 100
|
||||
}
|
||||
|
||||
module.exports = Meter
|
||||
9
api.hyungi.net/node_modules/tx2/src/utils/probes/units.js
generated
vendored
Normal file
9
api.hyungi.net/node_modules/tx2/src/utils/probes/units.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Time units, as found in Java:
|
||||
// see: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/TimeUnit.html
|
||||
exports.NANOSECONDS = 1 / (1000 * 1000);
|
||||
exports.MICROSECONDS = 1 / 1000;
|
||||
exports.MILLISECONDS = 1;
|
||||
exports.SECONDS = 1000 * exports.MILLISECONDS;
|
||||
exports.MINUTES = 60 * exports.SECONDS;
|
||||
exports.HOURS = 60 * exports.MINUTES;
|
||||
exports.DAYS = 24 * exports.HOURS;
|
||||
18
api.hyungi.net/node_modules/tx2/test/action.mocha.js
generated
vendored
Normal file
18
api.hyungi.net/node_modules/tx2/test/action.mocha.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
const tx2 = require('..')
|
||||
const should = require('should')
|
||||
|
||||
describe('Action', function() {
|
||||
it('should notify about new action', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('axm:action')
|
||||
should(dt.data.action_name).eql('something special')
|
||||
done()
|
||||
})
|
||||
|
||||
tx2.action('something special', (cb) => {
|
||||
cb({sucess:true})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
25
api.hyungi.net/node_modules/tx2/test/event.mocha.js
generated
vendored
Normal file
25
api.hyungi.net/node_modules/tx2/test/event.mocha.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
const tx2 = require('..')
|
||||
const should = require('should')
|
||||
|
||||
describe('Event', function() {
|
||||
it('should emit an event without data', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('human:event')
|
||||
done()
|
||||
})
|
||||
|
||||
tx2.event('something special')
|
||||
})
|
||||
|
||||
it('should emit an event with data', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('human:event')
|
||||
should(dt.data.yes).eql(true)
|
||||
done()
|
||||
})
|
||||
|
||||
tx2.event('something special', { yes : true })
|
||||
})
|
||||
|
||||
})
|
||||
25
api.hyungi.net/node_modules/tx2/test/issue.mocha.js
generated
vendored
Normal file
25
api.hyungi.net/node_modules/tx2/test/issue.mocha.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
const tx2 = require('..')
|
||||
const should = require('should')
|
||||
|
||||
describe('Issue', function() {
|
||||
it('should trigger an issue', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('process:exception')
|
||||
should(dt.stack).not.eql(null)
|
||||
done()
|
||||
})
|
||||
|
||||
tx2.issue(new Error('shit happens'))
|
||||
})
|
||||
|
||||
it('should trigger an issue v2', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('process:exception')
|
||||
should(dt.stack).not.eql(null)
|
||||
done()
|
||||
})
|
||||
|
||||
tx2.issue('shit happens')
|
||||
})
|
||||
})
|
||||
90
api.hyungi.net/node_modules/tx2/test/metric.mocha.js
generated
vendored
Normal file
90
api.hyungi.net/node_modules/tx2/test/metric.mocha.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
const tx2 = require('..')
|
||||
const should = require('should')
|
||||
|
||||
describe('Metric', function() {
|
||||
this.timeout(4000)
|
||||
|
||||
it('should register a metric', () => {
|
||||
tx2.metric({
|
||||
name: 'test',
|
||||
val: () => {
|
||||
return 20
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('should metric exists', () => {
|
||||
should(tx2.metricExists('test')).eql(true)
|
||||
})
|
||||
|
||||
it('should unknown metric not exists', () => {
|
||||
should(tx2.metricExists('unknowsss')).eql(false)
|
||||
})
|
||||
|
||||
it('should have metric present', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('axm:monitor')
|
||||
should(dt.data.test.value).eql(20)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should register metric v2', () => {
|
||||
tx2.metric('test2', () => {
|
||||
return 30
|
||||
})
|
||||
})
|
||||
|
||||
it('should have metric present', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('axm:monitor')
|
||||
should(dt.data.test2.value).eql(30)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('should register metric v3', () => {
|
||||
let m = tx2.metric('test3', 0)
|
||||
m.set(45)
|
||||
})
|
||||
|
||||
it('should have metric present', (done) => {
|
||||
tx2.once('data', (dt) => {
|
||||
should(dt.type).eql('axm:monitor')
|
||||
should(dt.data.test3.value).eql(45)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe('counter', () => {
|
||||
describe('inc', () => {
|
||||
const test = ({incBy, expectedValue}) => () => {
|
||||
const counter = tx2.counter('Test counter')
|
||||
counter.inc(incBy)
|
||||
should(counter.val()).eql(expectedValue)
|
||||
}
|
||||
|
||||
it('should increment by 1 when called with no arguments', test({expectedValue: 1}))
|
||||
it('should increment by 1 when called with 1', test({incBy: 1, expectedValue: 1}))
|
||||
it('should increment by -1 when called with -1', test({incBy: -1, expectedValue: -1}))
|
||||
it('should increment by 0 when called with 0', test({incBy: 0, expectedValue: 0}))
|
||||
it('should increment by 17.3 when called with 17.3', test({incBy: 17.3, expectedValue: 17.3}))
|
||||
})
|
||||
|
||||
describe('dec', () => {
|
||||
const test = ({decBy, expectedValue}) => () => {
|
||||
const counter = tx2.counter('Test counter')
|
||||
counter.dec(decBy)
|
||||
should(counter.val()).eql(expectedValue)
|
||||
}
|
||||
|
||||
it('should decrement by 1 when called with no arguments', test({expectedValue: -1}))
|
||||
it('should decrement by 1 when called with 1', test({decBy: 1, expectedValue: -1}))
|
||||
it('should decrement by -1 when called with -1', test({decBy: 1, expectedValue: -1}))
|
||||
it('should decrement by 0 when called with 0', test({decBy: 0, expectedValue: 0}))
|
||||
it('should decrement by 17.3 when called with 17.3', test({decBy: 17.3, expectedValue: -17.3}))
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user