diff --git a/.githooks/pre-commit/filter.sh b/.githooks/pre-commit/filter.sh old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore index a7039f8..883b4b2 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ assembly/ mocks_data/proxy/**/__* tms coverage +.nyc_output ############################ # visual studio code settings diff --git a/.travis.yml b/.travis.yml index c34937d..7cad407 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,20 @@ language: node_js -services: - - mysql node_js: - "8" - "9" - "10" +services: + - mysql +before_install: + - sudo mysql < ./packages/sandbox-core/test/fixtures/sql/initDB.sql 2>&1 + - export TZ=Asia/Shanghai install: - npm i - npm i codecov before_script: - - lerna bootstrap --no-ci - - lerna run build + - npm run bootstrap + - npm run build script: - npm run cov +after_script: + - codecov diff --git a/lerna.json b/lerna.json index 99ebddc..0be8f18 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "packages": [ "packages/*" ], - "version": "0.0.1" + "version": "0.0.2" } diff --git a/package.json b/package.json index 5d0970e..cc36b77 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,21 @@ "name": "sandbox", "private": true, "devDependencies": { + "nyc": "^11.2.1", "git-hooks": "^1.1.10", "lerna": "^3.4.0" }, + "nyc": { + "reporter": [ + "text", + "json", + "html", + "lcovonly" + ] + }, "scripts": { - "build": "lerna run build" + "bootstrap": "lerna bootstrap --no-ci", + "build": "lerna run build", + "cov": "sh scripts/cov.sh" } } diff --git a/packages/sandbox-core/package.json b/packages/sandbox-core/package.json index d48c9b6..27ce379 100644 --- a/packages/sandbox-core/package.json +++ b/packages/sandbox-core/package.json @@ -1,6 +1,6 @@ { "name": "sandbox-core", - "version": "0.0.1", + "version": "0.0.2", "main": "dist/index.js", "typings": "dist/index.d.ts", "dependencies": { @@ -13,7 +13,7 @@ "mysql2": "^1.5.3", "sequelize": "^4.39.0", "urllib": "^2.29.0", - "ws": "^6.0.0" + "ws": "^1.1.5" }, "devDependencies": { "@types/chai": "^4.1.4", @@ -28,6 +28,8 @@ "@types/urllib": "^2.28.0", "chai": "^3.5.0", "midway-bin": "^0.3.8", + "midway-mock": "^0.4.2", + "mm": "^2.4.1", "mocha": "^3.5.0", "nyc": "^11.2.1", "ts-node": "^4.1.0", @@ -38,7 +40,8 @@ "prepublishOnly": "npm run build", "lint": "tslint --fix -p .", "build": "npm run lint && rm -rf ./dist && tsc", - "test": "midway-bin test --ts" + "test": "midway-bin test --ts", + "cov": "midway-bin cov --ts" }, "files": [ "dist", diff --git a/packages/sandbox-core/src/core/debugServer/cipher.ts b/packages/sandbox-core/src/core/debugServer/cipher.ts index 73e8864..c59b3fe 100644 --- a/packages/sandbox-core/src/core/debugServer/cipher.ts +++ b/packages/sandbox-core/src/core/debugServer/cipher.ts @@ -1,26 +1,38 @@ import crypto = require('crypto'); -const secret = 'midway_sandbox'; +import { provide, async, scope, ScopeEnum, config } from 'midway-mirror'; +@scope(ScopeEnum.Singleton) +@async() +@provide() export class Cipher { - static encrypt(value: string) { - if ('string' !== typeof value) { - throw new Error('value required'); - } - const cipher = crypto.createCipher('des', secret); + @config('cipher') + config; + + encrypt(value: string) { + this.paramCheck(value); + const cipher = crypto.createCipher('des', this.config.secret); return cipher.update(value, 'utf8', 'hex') + cipher.final('hex'); } - static decrypt(value: string) { - if ('string' !== typeof value) { - throw new Error('value required'); - } + decrypt(value: string) { + this.paramCheck(value); try { - const decipher = crypto.createDecipher('des', secret); + const decipher = crypto.createDecipher('des', this.config.secret); return decipher.update(value, 'hex', 'utf8') + decipher.final('utf8'); } catch (e) { return ''; } } + private paramCheck(value: string) { + if ('string' !== typeof value) { + throw new Error('value required'); + } + // 必须 在 config 中配置 cipher.secret + if (!this.config.secret) { + throw new Error('cipher secret config required'); + } + } + } diff --git a/packages/sandbox-core/src/core/debugServer/debugServer.ts b/packages/sandbox-core/src/core/debugServer/debugServer.ts index d7e154a..7e964b5 100644 --- a/packages/sandbox-core/src/core/debugServer/debugServer.ts +++ b/packages/sandbox-core/src/core/debugServer/debugServer.ts @@ -5,16 +5,21 @@ import WebSocket = require('ws'); import {Server as WebSocketServer} from 'ws'; import urllib = require('urllib'); import {Server as HTTPServer} from 'http'; +import { provide, inject, autowire } from 'midway-mirror'; import {Cipher} from './cipher'; +@provide() +@autowire(false) export class DebugServer extends EventEmitter { + @inject() + cipher: Cipher; + private httpServer: HTTPServer; private wsServer: WebSocketServer; private logger = console; - public constructor (server) { - super(); + public setServer(server) { this.httpServer = server; } @@ -36,16 +41,16 @@ export class DebugServer extends EventEmitter { try { - const url = request.url; + const upgradeReq = socket.upgradeReq; + const url = upgradeReq.url; if (!url.startsWith('/remoteDebug')) { socket.terminate(); return; } - socket.pause(); const query = QueryString.parse(Url.parse(url).query); const tokenRaw: string = query.token as any; - const info = JSON.parse(Cipher.decrypt(tokenRaw)); + const info = JSON.parse(this.cipher.decrypt(tokenRaw)); info.host = info.ip; this.logger.log('ws', url); diff --git a/packages/sandbox-core/src/core/manager/errorManager.ts b/packages/sandbox-core/src/core/manager/errorManager.ts index ec58dc2..0f5406c 100644 --- a/packages/sandbox-core/src/core/manager/errorManager.ts +++ b/packages/sandbox-core/src/core/manager/errorManager.ts @@ -121,6 +121,7 @@ export class ErrorManager { attributes: [['log_path', 'path']], where: { [Sequelize.Op.and]: required }, group: ['path'], + raw: true, }; return this.errorModel.findAll(conditions); } @@ -133,20 +134,23 @@ export class ErrorManager { ], where: { [Sequelize.Op.and]: required }, group: ['errType'], + raw: true, }; return this.errorModel.findAll(conditions); } private findErrorTypeDist(required: object[]) { + const downSampling = Sequelize.literal('(unix_timestamp - unix_timestamp % 60)'); const conditions: SearchCondition = { attributes: [ ['error_type', 'errType'], [Sequelize.fn('COUNT', Sequelize.literal('*')), 'cnt'], - [Sequelize.literal('(unix_timestamp - unix_timestamp % 60)'), 'timestamp'], + [downSampling, 'timestamp'], ], where: { [Sequelize.Op.and]: required }, - group: ['timestamp', 'errType'], + group: [downSampling, 'errType'], order: [['timestamp', 'DESC']], + raw: true, }; return this.errorModel.findAll(conditions); } diff --git a/packages/sandbox-core/src/core/model/dw/sandboxGalaxySlsTraces.ts b/packages/sandbox-core/src/core/model/dw/sandboxGalaxySlsTraces.ts index 6aa94a1..52a4cb9 100644 --- a/packages/sandbox-core/src/core/model/dw/sandboxGalaxySlsTraces.ts +++ b/packages/sandbox-core/src/core/model/dw/sandboxGalaxySlsTraces.ts @@ -41,65 +41,39 @@ export async function factory(context: IApplicationContext) { type: Sequelize.TEXT, field: 'trace_name', }, + traceSpans: { + type: Sequelize.TEXT, + field: 'trace_spans', + }, traceId: { type: Sequelize.STRING(256), field: 'trace_id', }, - uuid: { - type: Sequelize.STRING(256), - allowNull: false, - }, - spanName: { - type: Sequelize.STRING(512), - field: 'span_name', - }, - spanTimestamp: { - type: Sequelize.STRING(128), - field: 'span_timestamp', - }, - spanDuration: { + traceDuration: { type: Sequelize.INTEGER, - field: 'span_duration', - }, - spanError: { - type: Sequelize.INTEGER(4), - allowNull: true, - defaultValue: 0, - field: 'span_error', + field: 'trace_duration', }, - spanType: { + traceStatus: { type: Sequelize.INTEGER, - field: 'span_type', - }, - spanMethod: { - type: Sequelize.STRING(128), - field: 'span_method', - }, - spanTarget: { - type: Sequelize.TEXT, - field: 'span_target', + field: 'trace_status', + defaultValue: 1, }, - spanCode: { - type: Sequelize.STRING(128), - field: 'span_code', - }, - spanTags: { - type: Sequelize.TEXT, - field: 'span_tags', + uuid: { + type: Sequelize.STRING(256), + allowNull: false, }, - spanId: { - type: Sequelize.STRING(128), - field: 'span_id', + unixTimestamp: { + type: Sequelize.BIGINT, + field: 'unix_timestamp', }, - spanRpcId: { - type: Sequelize.STRING(128), - field: 'span_rpcid', + version: { + type: Sequelize.INTEGER, }, }, { timestamps: false, underscored: false, freezeTableName: true, - tableName: 'sandbox_galaxy_sls_trace_nodes', + tableName: 'sandbox_galaxy_sls_traces', }); SLSTraceModel.removeAttribute('id'); diff --git a/packages/sandbox-core/src/core/service/remoteDebugService.ts b/packages/sandbox-core/src/core/service/remoteDebugService.ts index 5fb9e97..93a08de 100644 --- a/packages/sandbox-core/src/core/service/remoteDebugService.ts +++ b/packages/sandbox-core/src/core/service/remoteDebugService.ts @@ -14,6 +14,9 @@ export class RemoteDebugService implements IRemoteDebugService { @inject('privilegeAdapter') privilegeAdapter: IPrivilegeAdapter; + @inject() + cipher: Cipher; + async getDebuggableHost(options: HostSelector & AppSelector & UserSelector): Promise { const {scope, scopeName, uid} = options; const hasPermission = await this.privilegeAdapter.isAppOps(scope, scopeName, uid); @@ -22,7 +25,7 @@ export class RemoteDebugService implements IRemoteDebugService { } const debuggableProcesses = await this.pandoraAdapter.getDebuggableProcesses(options); for (const process of debuggableProcesses) { - process.token = Cipher.encrypt(JSON.stringify({ + process.token = this.cipher.encrypt(JSON.stringify({ debugPort: process.debugPort, ip: options.ip, webSocketDebuggerUrl: process.webSocketDebuggerUrl, diff --git a/packages/sandbox-core/test/app/controller/applicationCtrl.test.ts b/packages/sandbox-core/test/app/controller/applicationCtrl.test.ts new file mode 100644 index 0000000..cb42671 --- /dev/null +++ b/packages/sandbox-core/test/app/controller/applicationCtrl.test.ts @@ -0,0 +1,89 @@ +import * as assert from 'assert'; +import { Op } from 'sequelize'; +import { getInstance } from '../../helper'; +import applicationMockData from '../../fixtures/mockData/applicationMockData'; + +describe('applicationCtrltest', async () => { + + before(async () => { + const applicationModel = await getInstance('applicationModel'); + await Promise.all([ + applicationModel.bulkCreate(applicationMockData), + ]); + }); + + it('listByUser', async () => { + const applicationCtrl = await getInstance('applicationCtrl'); + const ctx = { + uid: '1001', + query: { + offset: 0, + }, + }; + await applicationCtrl.listByUser(ctx); + assert((ctx as any).body.success === true); + }); + + it('groupUpsert', async () => { + const applicationCtrl = await getInstance('applicationCtrl'); + const ctx = { + request: { + body: { + groupName: 'test_group', + hostList: [{ip: '10.0.0.1', hostname: 'devServer'}], + scope: 'test', + scopeName: 'sandbox-test', + }, + }, + }; + await applicationCtrl.groupUpsert(ctx); + assert((ctx as any).body); + }); + + it('groupExist', async () => { + const applicationCtrl = await getInstance('applicationCtrl'); + const ctx = { + query: { + groupName: 'test_group', + scope: 'test', + scopeName: 'sandbox-test', + }, + }; + await applicationCtrl.groupExist(ctx); + assert((ctx as any).body); + }); + + it('groupDelete', async () => { + const applicationCtrl = await getInstance('applicationCtrl'); + const ctx = { + request: { + body: { + groupName: 'test_group', + scope: 'test', + scopeName: 'sandbox-test', + }, + }, + }; + await applicationCtrl.groupDelete(ctx); + assert((ctx as any).body); + }); + + after(async () => { + const applicationModel = await getInstance('applicationModel'); + await applicationModel.destroy({ + where: { + alinodeToken: { + [Op.in]: applicationMockData.map((app) => app.alinodeToken), + }, + }, + }); + const groupModel = await getInstance('groupModel'); + await groupModel.destroy({ + where: { + groupName: 'test_group', + scope: 'test', + scopeName: 'sandbox-test', + }, + }); + }); +}); diff --git a/packages/sandbox-core/test/app/controller/errorCtrl.test.ts b/packages/sandbox-core/test/app/controller/errorCtrl.test.ts new file mode 100644 index 0000000..e3b125d --- /dev/null +++ b/packages/sandbox-core/test/app/controller/errorCtrl.test.ts @@ -0,0 +1,50 @@ +import * as assert from 'assert'; +import { Op } from 'sequelize'; +import { getInstance } from '../../helper'; +import errorMockData from '../../fixtures/mockData/errorMockData'; + +describe('errorCtrlTest', async () => { + + before(async () => { + const errorModel = await getInstance('errorModel'); + await errorModel.bulkCreate(errorMockData); + }); + + it('queryErrors', async () => { + const errorCtrl = await getInstance('errorCtrl'); + const ctx = { + request: { + query: { + scopeName: 'sandbox-test', + }, + }, + }; + await errorCtrl.queryErrors(ctx); + assert((ctx as any).body.success === false); + assert((ctx as any).body.error.name === 'GetSLSLogError'); + }); + + it('queryErrorTypes', async () => { + const errorCtrl = await getInstance('errorCtrl'); + const ctx = { + request: { + query: { + scopeName: 'sandbox-test', + }, + }, + }; + await errorCtrl.queryErrorTypes(ctx); + assert((ctx as any).body.success === true); + }); + + after(async () => { + const errorModel = await getInstance('errorModel'); + await errorModel.destroy({ + where: { + uuid: { + [Op.in]: errorMockData.map((e) => e.uuid), + }, + }, + }); + }); +}); diff --git a/packages/sandbox-core/test/core/debugServer/cipher.test.ts b/packages/sandbox-core/test/core/debugServer/cipher.test.ts new file mode 100644 index 0000000..af75578 --- /dev/null +++ b/packages/sandbox-core/test/core/debugServer/cipher.test.ts @@ -0,0 +1,34 @@ +import * as assert from 'assert'; +import { getInstance } from '../../helper'; +import { Cipher } from '../../../src/core/debugServer/cipher'; + +describe('/src/core/debugServer/cipher.ts', () => { + + let cipher: Cipher; + + before(async() => { + cipher = await getInstance('cipher'); + }); + + it('should encrypt/decrypt ok', () => { + const plainText = 'hello world'; + const cipherText = cipher.encrypt(plainText); + assert(plainText === cipher.decrypt(cipherText)); + }); + + it('should throw error when pass null to encrypt/decrypt', () => { + assert.throws(() => { + cipher.decrypt(null); + }, /value required/); + }); + + it('should throw error when secret is missing', async () => { + const rawSecret = cipher.config.secret; + cipher.config.secret = undefined; + assert.throws(() => { + cipher.encrypt('hello world'); + }, /secret config required/); + cipher.config.secret = rawSecret; + }); + +}); diff --git a/packages/sandbox-core/test/core/debugServer/debugServer.test.ts b/packages/sandbox-core/test/core/debugServer/debugServer.test.ts new file mode 100644 index 0000000..13647cb --- /dev/null +++ b/packages/sandbox-core/test/core/debugServer/debugServer.test.ts @@ -0,0 +1,78 @@ +import * as http from 'http'; +import * as assert from 'assert'; +import { spawn } from 'child_process'; +import * as WebSocket from 'ws'; +import { once } from 'lodash'; +import { DebugServer } from '../../../src/core/debugServer/debugServer'; +import { Cipher } from '../../../src/core/debugServer/cipher'; +import { getInstance } from '../../helper'; + +describe('src/core/debugServer/debugServer.ts', () => { + + let debugableProcess; + let debugServer: DebugServer; + let token; + const logger = console; + let cipher: Cipher; + + before(async () => { + debugableProcess = spawn('node', ['--inspect=5858']); + debugableProcess.on('error', logger.error); + + const httpServer = http.createServer(); + httpServer.listen(3322); + debugServer = await getInstance('debugServer'); + debugServer.setServer(httpServer); + debugServer.start(); + cipher = await getInstance('cipher'); + token = cipher.encrypt(JSON.stringify({ + ip: '127.0.0.1', + })); + }); + + it('should connect debug server', (done) => { + const client = new WebSocket('ws://127.0.0.1:3322/remoteDebug?token=' + token); + + client.on('open', () => { + client.send('{}'); + }); + const doneOnce = once(done); + client.on('message', (data) => { + assert(JSON.parse(data)); + client.terminate(); + client.on('close', () => { + doneOnce(); + }); + + }); + }); + + it('should closed by debug server', (done) => { + const client = new WebSocket('ws://127.0.0.1:3322/foobar?token=' + token); + client.on('close', () => { + done(); + }); + setTimeout(done.bind(null, new Error('socket not closed in 3s')), 3000); + }); + + it('should report a Error: Cannot found any instance', (done) => { + const mockServer = http.createServer((req, res) => req.pipe(res)); + mockServer.listen(5859); + const mockToken = cipher.encrypt(JSON.stringify({ + ip: '127.0.0.1', + debugPort: '5859', + })); + const client = new WebSocket('ws://127.0.0.1:3322/remoteDebug?token=' + mockToken); + client.on('close', () => done()); + }); + + it('should report a Error: Unexpected end of JSON input', (done) => { + const client = new WebSocket('ws://127.0.0.1:3322/remoteDebug?token=' + token.slice(0, -10)); + client.on('close', () => done()); + }); + + after(() => { + debugableProcess.kill(); + }); + +}); diff --git a/packages/sandbox-core/test/core/manager/metricsManager.test.ts b/packages/sandbox-core/test/core/manager/metricsManager.test.ts new file mode 100644 index 0000000..d8ae59e --- /dev/null +++ b/packages/sandbox-core/test/core/manager/metricsManager.test.ts @@ -0,0 +1,249 @@ +import * as assert from 'assert'; +import {MetricsManager} from '../../../src/core/manager/metricsManager'; +import { getInstance } from '../../helper'; +import { expect } from 'chai'; +import mm = require('mm'); + +describe('test/core/manager/metricsManager.test.ts', () => { + + it('should static pickLatestDp() be ok', () => { + const latest = MetricsManager.pickLatestDp({ + 123: '123', + 456: '456', + 1000: 'latest', + }); + assert('latest' === latest); + }); + + it('should getMetricsNames() be ok', async () => { + const metricsManager: MetricsManager = await getInstance('metricsManager'); + const res = await metricsManager.getMetricsNames({ + scope: 'test', + scopeName: 'test', + }); + assert(res.length === 3); + assert(res[0] === 'cpu'); + assert(res[1] === 'mem'); + assert(res[2] === 'qps'); + }); + + it('should frontEndAnalyse() with analyseHigherLower=true be ok', async () => { + + const metricsManager: MetricsManager = await getInstance('metricsManager'); + const res = metricsManager.frontEndAnalyse( + {analyseHigherLower: true}, + [{ metric: 'testName', aggregator: 'avg' }], + [ + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-a', + trend: [ + { time: 1, value: 1 }, + { time: 2, value: 1 }, + ], + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-b', + trend: [ + { time: 1, value: 2 }, + { time: 2, value: 2 }, + ], + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-b', + trend: [ + { time: 1, value: 3 }, + { time: 2, value: 3 }, + ], + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-c', + trend: [ + { time: 1, value: 4 }, + { time: 2, value: 4 }, + ], + }, + ], + ); + + expect(res).to.deep.equal( + [ + { + metric: 'testName', + aggregator: 'avg', + frontEndAggregator: 'avg', + trend: [ + { + time: 1, + value: 2.5, + }, + { + time: 2, + value: 2.5, + }, + ], + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-c', + trend: [ + { + time: 1, + value: 4, + }, + { + time: 2, + value: 4, + }, + ], + frontEndAggregator: 'highest', + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-a', + trend: [ + { + time: 1, + value: 1, + }, + { + time: 2, + value: 1, + }, + ], + frontEndAggregator: 'lowest', + }, + ], + ); + }); + + it('should frontEndAnalyse() with analyseHigherLower=false be ok', async () => { + const input = [ + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-a', + trend: [ + { time: 1, value: 1 }, + { time: 2, value: 1 }, + ], + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-b', + trend: [ + { time: 1, value: 2 }, + { time: 2, value: 2 }, + ], + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-b', + trend: [ + { time: 1, value: 3 }, + { time: 2, value: 3 }, + ], + }, + { + metric: 'testName', + aggregator: 'avg', + hostname: 'host-c', + trend: [ + { time: 1, value: 4 }, + { time: 2, value: 4 }, + ], + }, + ]; + const metricsManager: MetricsManager = await getInstance('metricsManager'); + const res = metricsManager.frontEndAnalyse( + {analyseHigherLower: false}, + [{ metric: 'testName', aggregator: 'avg' }], + input, + ); + expect(res).to.be.equal(input); + }); + + it('should getLatestMetricByAppSelectorAndGroupByEachHost() be ok', async () => { + const metricsManager: MetricsManager = await getInstance('metricsManager'); + mm(metricsManager, 'tsdb', { + query(queryOpts) { + return [ + { + tags: { + hostname: 'host-a', + ip: '192.168.2.1', + }, + dps: { + 1: 11, + 2: 12, + 3: 13, + }, + }, + { + tags: { + hostname: 'host-b', + ip: '192.168.2.2', + }, + dps: { + 1: 21, + 2: 22, + 3: 23, + }, + }, + { + tags: { + hostname: 'host-c', + ip: '192.168.2.3', + }, + dps: { + 1: 31, + 2: 32, + 3: 33, + }, + }, + ]; + }, + }); + const res = await metricsManager.getLatestMetricByAppSelectorAndGroupByEachHost( + { + metric: 'testName', + }, + { + scope: 'test', + scopeName: 'test', + }, + ); + expect(res).to.deep.equal( + [ + { + hostname: 'host-a', + ip: '192.168.2.1', + value: 13, + }, + { + hostname: 'host-b', + ip: '192.168.2.2', + value: 23, + }, + { + hostname: 'host-c', + ip: '192.168.2.3', + value: 33, + }, + ], + ); + mm.restore(); + }); + +}); diff --git a/packages/sandbox-core/test/core/manager/traceManager.test.ts b/packages/sandbox-core/test/core/manager/traceManager.test.ts new file mode 100644 index 0000000..2f85743 --- /dev/null +++ b/packages/sandbox-core/test/core/manager/traceManager.test.ts @@ -0,0 +1,87 @@ +import { getInstance } from '../../helper'; +import * as assert from 'assert'; +import { Op } from 'sequelize'; +import traceMockData from '../../fixtures/mockData/traceMockData'; +import keyTraceMockData from '../../fixtures/mockData/keyTraceMockData'; + +describe('test/core/manager/traceManager.test.ts', () => { + before(async () => { + const keyTraceModel = await getInstance('keyTraceModel'); + await keyTraceModel.bulkCreate(keyTraceMockData); + const traceModel = await getInstance('traceModel'); + await traceModel.bulkCreate(traceMockData.traces); + const traceNodeModel = await getInstance('traceNodeModel'); + await traceNodeModel.bulkCreate(traceMockData.traceNodes); + }); + + it('traceSummaryList', async () => { + const traceManager = await getInstance('traceManager'); + const res = await traceManager.traceSummaryList({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + }, { + order: 'env', + limit: 10, + offset: 10, + }); + assert(res.length === 0); + }); + + it('listTraceByName', async () => { + const traceManager = await getInstance('traceManager'); + let res = await traceManager.listTraceByName({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }, { + attributes: ['scope', 'scopeName'], + order: 'timestamp,desc|traceDuration,asc', + limit: 10, + offset: 10, + }); + assert(res.count === 1 && res.rows.length === 0); + + res = await traceManager.listTraceByName({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }, {}); + assert(res.count === 1 && res.rows.length === 1); + }); + + after(async () => { + const keyTraceModel = await getInstance('keyTraceModel'); + await keyTraceModel.destroy({ + where: { + traceName: { + [Op.in]: keyTraceMockData.map((kt) => kt.traceName), + }, + }, + }); + const traceModel = await getInstance('traceModel'); + await traceModel.destroy({ + where: { + uuid: { + [Op.in]: traceMockData.traces.map((tr) => tr.uuid), + }, + }, + }); + const traceNodeModel = await getInstance('traceNodeModel'); + await traceNodeModel.destroy({ + where: { + uuid: { + [Op.in]: traceMockData.traceNodes.map((tr) => tr.uuid), + }, + }, + }); + }); + +}); diff --git a/packages/sandbox-core/test/core/manager/traceNodeManager.test.ts b/packages/sandbox-core/test/core/manager/traceNodeManager.test.ts new file mode 100644 index 0000000..051b2b7 --- /dev/null +++ b/packages/sandbox-core/test/core/manager/traceNodeManager.test.ts @@ -0,0 +1,74 @@ +import { getInstance } from '../../helper'; +import * as assert from 'assert'; +import { Op } from 'sequelize'; +import traceMockData from '../../fixtures/mockData/traceMockData'; +import keyTraceMockData from '../../fixtures/mockData/keyTraceMockData'; + +describe('traceNodeManager', () => { + before(async () => { + const keyTraceModel = await getInstance('keyTraceModel'); + await keyTraceModel.bulkCreate(keyTraceMockData); + const traceModel = await getInstance('traceModel'); + await traceModel.bulkCreate(traceMockData.traces); + const traceNodeModel = await getInstance('traceNodeModel'); + await traceNodeModel.bulkCreate(traceMockData.traceNodes); + }); + + it('listNodesByTarget', async () => { + const traceManager = await getInstance('traceNodeManager'); + let res = await traceManager.listNodesByTarget({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + spanName: 'configs', + spanTarget: '/', + }, { + attributes: ['scope', 'scopeName'], + order: 'timestamp,desc|spanCode,asc', + limit: 10, + offset: 10, + }); + assert(res.count === 1 && res.rows.length === 0); + + res = await traceManager.listNodesByTarget({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + spanName: 'configs', + spanTarget: '/', + }, {}); + assert(res.count === 1 && res.rows.length === 1); + }); + + after(async () => { + const keyTraceModel = await getInstance('keyTraceModel'); + await keyTraceModel.destroy({ + where: { + traceName: { + [Op.in]: keyTraceMockData.map((kt) => kt.traceName), + }, + }, + }); + const traceModel = await getInstance('traceModel'); + await traceModel.destroy({ + where: { + uuid: { + [Op.in]: traceMockData.traces.map((tr) => tr.uuid), + }, + }, + }); + const traceNodeModel = await getInstance('traceNodeModel'); + await traceNodeModel.destroy({ + where: { + uuid: { + [Op.in]: traceMockData.traceNodes.map((tr) => tr.uuid), + }, + }, + }); + }); + +}); diff --git a/packages/sandbox-core/test/core/service/applicationService.test.ts b/packages/sandbox-core/test/core/service/applicationService.test.ts index f135aaa..0c480f3 100644 --- a/packages/sandbox-core/test/core/service/applicationService.test.ts +++ b/packages/sandbox-core/test/core/service/applicationService.test.ts @@ -22,13 +22,6 @@ describe('applicationServiceTest', () => { assert(xor(res.data.map((app) => app.flag), applicationMockData.map((app) => app.flag)).length === 0); }); - it('queryGroups', async () => { - const appService = await getInstance('applicationService'); - const res = await appService.queryGroups({ scope: 'test', scopeName: 'sandbox-test' }); - assert(res); - assert(isEqual(res.dev, defaultPlatformHostsMockData.dev)); - }); - it('queryHosts', async () => { const appService = await getInstance('applicationService'); const res = await appService.queryHosts({ env: 'dev', scope: 'test'}); @@ -41,11 +34,39 @@ describe('applicationServiceTest', () => { const appService = await getInstance('applicationService'); const res = await appService.groupUpsert({ groupName: 'test_group', - hostList: [], + hostList: [{ip: '10.0.0.1', hostname: 'devServer'}], + scope: 'test', + scopeName: 'sandbox-test', + }); + assert(typeof res === 'boolean'); + }); + + it('queryGroups', async () => { + const appService = await getInstance('applicationService'); + const res = await appService.queryGroups({ scope: 'test', scopeName: 'sandbox-test' }); + assert(res); + assert(isEqual(res.dev, defaultPlatformHostsMockData.dev)); + }); + + it('groupUpsert with empty host list', async () => { + const appService = await getInstance('applicationService'); + const res = await appService.groupUpsert({ + groupName: 'test_group_no_host', + hostList: null, + scope: 'test', + scopeName: 'sandbox-test', + }); + assert(typeof res === 'boolean'); + }); + + it('groupExist', async () => { + const appService = await getInstance('applicationService'); + const res = await appService.groupExist({ + groupName: 'test_group', scope: 'test', scopeName: 'sandbox-test', }); - assert(res === true); + assert(res === 1); }); it('groupDelete', async () => { diff --git a/packages/sandbox-core/test/core/service/errorService.test.ts b/packages/sandbox-core/test/core/service/errorService.test.ts index 9f853c0..dcdfcef 100644 --- a/packages/sandbox-core/test/core/service/errorService.test.ts +++ b/packages/sandbox-core/test/core/service/errorService.test.ts @@ -12,7 +12,7 @@ describe('errorServiceTest', () => { it('queryErrors', async () => { const errorService = await getInstance('errorService'); - const res = await errorService.queryErrors({ + const baseOptions = { startTime: new Date('2018-09-20 00:00:00'), endTime: new Date('2018-09-20 03:00:00'), scope: 'test', @@ -20,9 +20,33 @@ describe('errorServiceTest', () => { env: 'dev', page: 1, pageSize: 10, - }); + }; + let res = await errorService.queryErrors(baseOptions); assert(res.count === 3 && res.rows.length === 3); assert(xor(res.rows.map((row) => row.uuid), errorMockData.map((data) => data.uuid)).length === 0); + + res = await errorService.queryErrors({ + ip: '192.168.1.1', + errType: ['RangeError'], + keyword: '483d9c50-c303-11e8-a355-529269fb1459', + in: 'traceId', ...baseOptions}); + assert(res.count === 1 && res.rows.length === 1); + assert(res.rows[0].traceId === '483d9c50-c303-11e8-a355-529269fb1459'); + + res = await errorService.queryErrors({ + keyword: 'RangeError', + in: 'errorType', ...baseOptions}); + assert(res.count === 2 && res.rows.length === 2); + assert(res.rows.every((row) => row.errorType === 'RangeError')); + + res = await errorService.queryErrors({ + keyword: '192.168.1.2', + in: 'machine', ...baseOptions}); + assert(res.count === 0 && res.rows.length === 0); + + res = await errorService.queryErrors({ + keyword: 'emitTwo', ...baseOptions}); + assert(res.count === 3 && res.rows.length === 3); }); it('queryErrorTypes', async () => { @@ -38,6 +62,7 @@ describe('errorServiceTest', () => { }); assert(res[0].length === 2); assert(res[1].length === 2); + assert(res[1].some((data) => data.errType === 'RangeError' && data.cnt === 2)); assert(res[1].some((data) => data.errType === 'ReferenceError' && data.cnt === 1)); assert(res[2].length === 2); diff --git a/packages/sandbox-core/test/core/service/metricsService.test.ts b/packages/sandbox-core/test/core/service/metricsService.test.ts index 4e58172..26d406a 100644 --- a/packages/sandbox-core/test/core/service/metricsService.test.ts +++ b/packages/sandbox-core/test/core/service/metricsService.test.ts @@ -1,21 +1,307 @@ -// import * as assert from 'assert'; -// import { getInstance } from '../../helper'; - -describe('metricsServiceTest', () => { -// before(async () => { -// }); -// -// it('getMetricsNames', async () => { -// }); -// -// it('getCustomMetricsNames', async () => {}); -// -// it('queryMetricsLatest', async () => {}); -// -// it('queryMetricsTrend', async () => {}); -// -// it('queryHostsMap', async () => {}); -// -// after(async () => { -// }); +import * as assert from 'assert'; +import { getInstance } from '../../helper'; +import mm = require('mm'); +import { expect } from 'chai'; +import {MetricsService} from '../../../src/core/service/metricsService'; + +describe('metricsService.test.ts', () => { + + afterEach(() => { + mm.restore(); + }); + + it('should getMetricsNames() be ok', async () => { + const metricsService: MetricsService = await getInstance('metricsService'); + const res = await metricsService.getMetricsNames({ + scope: 'test', + scopeName: 'test', + }); + assert(res.length === 3); + assert(res[0] === 'cpu'); + assert(res[1] === 'mem'); + assert(res[2] === 'qps'); + }); + + it('should getCustomMetricsNames() be ok', async () => { + const metricsService: MetricsService = await getInstance('metricsService'); + mm(metricsService.metricsManager, 'getMetricsNames', () => { + return ['system.a', 'node.b', 'error.c', 'middleware.d', 'ok', 'yes', 'custom.xxx']; + }); + const res = await metricsService.getCustomMetricsNames({ + scope: 'test', + scopeName: 'test', + }); + expect(res).to.deep.equal(['ok', 'yes', 'custom.xxx']); + }); + + it('should queryMetricsLatest() be ok', async () => { + const metricsService: MetricsService = await getInstance('metricsService'); + mm(metricsService, 'tsdb', { + query: async (query) => { + assert(query.start === '6m-ago'); + assert(query.queries[0].metric === 'testName1'); + assert(query.queries[0].aggregator === 'avg'); + assert(query.queries[0].downsample === '1m-last'); + assert(query.queries[0].tags.scope === 'test'); + assert(query.queries[0].tags.scope_name === 'test'); + assert(query.queries[0].tags.env === 'test'); + assert(query.queries[1].metric === 'testName2'); + assert(query.queries[1].aggregator === 'avg'); + assert(query.queries[1].downsample === '1m-last'); + assert(query.queries[1].tags.scope === 'test'); + assert(query.queries[1].tags.scope_name === 'test'); + assert(query.queries[1].tags.env === 'test'); + assert(query.queries.length === 2); + return [ + { + metric: 'testName1', + query: { + metric: 'testName1', + aggregator: 'avg', + }, + dps: { + 1: 11, + 2: 12, + 3: 13, + }, + }, + { + metric: 'testName2', + query: { + metric: 'testName2', + aggregator: 'avg', + }, + dps: { + 1: 21, + 2: 22, + 3: 23, + }, + }, + ]; + }, + }); + const res = await metricsService.queryMetricsLatest({ + scope: 'test', scopeName: 'test', env: 'test', + metricsNames: [ + { metric: 'testName1', aggregator: 'avg' }, + { metric: 'testName2', aggregator: 'avg' }, + ], + }); + expect(res).to.deep.equal( + [ { latest: 13 }, { latest: 23 } ], + ); + }); + + it('should queryMetricsTrend() be ok', async () => { + const metricsService: MetricsService = await getInstance('metricsService'); + mm(metricsService, 'tsdb', { + query: async (query) => { + assert(query.start === 123); + assert(query.end === 456); + assert(query.queries[0].metric === 'testName1'); + assert(query.queries[0].aggregator === 'avg'); + assert(query.queries[0].tags.scope === 'test'); + assert(query.queries[0].tags.scope_name === 'test'); + assert(query.queries[0].tags.env === 'test'); + assert(query.queries[1].metric === 'testName2'); + assert(query.queries[1].aggregator === 'avg'); + assert(query.queries[1].tags.scope === 'test'); + assert(query.queries[1].tags.scope_name === 'test'); + assert(query.queries[1].tags.env === 'test'); + assert(query.queries.length === 2); + return [ + { + metric: 'testName1', + query: { + metric: 'testName1', + aggregator: 'avg', + }, + tags: { + hostname: 'host-a', + ip: '192.168.1.1', + pid: 1, + }, + dps: { + 1: 11, + 2: 12, + 3: 13, + }, + }, + { + metric: 'testName2', + query: { + metric: 'testName2', + aggregator: 'avg', + }, + tags: { + hostname: 'host-b', + ip: '192.168.1.2', + pid: 2, + }, + dps: { + 1: 21, + 2: 22, + 3: 23, + }, + }, + ]; + }, + }); + const res = await metricsService.queryMetricsTrend({ + scope: 'test', + scopeName: 'test', + env: 'test', + startTime: 123, + endTime: 456, + metricsNames: [ + { metric: 'testName1', aggregator: 'avg' }, + { metric: 'testName2', aggregator: 'avg' }, + ], + }); + expect(res).to.deep.equal([ + { + trend: [ + { + time: 1, + value: 11, + }, + { + time: 2, + value: 12, + }, + { + time: 3, + value: 13, + }, + ], + aggregator: 'avg', + metric: 'testName1', + hostname: 'host-a', + ip: '192.168.1.1', + pid: 1, + }, + { + trend: [ + { + time: 1, + value: 21, + }, + { + time: 2, + value: 22, + }, + { + time: 3, + value: 23, + }, + ], + aggregator: 'avg', + metric: 'testName2', + hostname: 'host-b', + ip: '192.168.1.2', + pid: 2, + }, + ]); + }); + + it('should queryHostsMap() be ok', async () => { + + const calledTimes = []; + const metricsService: MetricsService = await getInstance('metricsService'); + + mm(metricsService, 'metricsManager', { + getLatestMetricByAppSelectorAndGroupByEachHost: async (metricsName, appSelector) => { + calledTimes.push(metricsName); + assert(appSelector.scope === 'test'); + assert(appSelector.scopeName === 'test'); + assert(appSelector.env === 'test'); + return [ + { + hostname: 'host-a', + ip: '192.168.2.1', + value: 13, + }, + { + hostname: 'host-b', + ip: '192.168.2.2', + value: 23, + }, + { + hostname: 'host-d', + ip: '192.168.2.4', + value: 43, + }, + ]; + }, + }); + mm(metricsService, 'applicationService', { + queryGroups(app) { + assert(app.scope === 'test'); + assert(app.scopeName === 'test'); + return { + test: [ + { + name: 'group_1', + hosts: [ + { + ip: '192.168.2.1', + hostname: 'host-a', + }, + { + ip: '192.168.2.2', + hostname: 'host-b', + }, + { + ip: '192.168.2.3', + hostname: 'host-c', + }, + ], + }, + ], + }; + }, + }); + + const res = await metricsService.queryHostsMap({ + scope: 'test', + scopeName: 'test', + env: 'test', + metricsNames: [ + { metric: 'testName1', aggregator: 'avg' }, + { metric: 'testName2', aggregator: 'avg' }, + ], + }); + + expect(res).to.deep.equal([ + { + name: 'group_1', + hosts: [ + { + ip: '192.168.2.1', + hostname: 'host-a', + testName1: 13, + testName2: 13, + }, + { + ip: '192.168.2.2', + hostname: 'host-b', + testName1: 23, + testName2: 23, + }, + { + ip: '192.168.2.3', + hostname: 'host-c', + }, + ], + }, + ], + ); + + expect(calledTimes).to.deep.equal([ + { metric: 'testName1', aggregator: 'avg' }, + { metric: 'testName2', aggregator: 'avg' }, + ]); + + }); + }); diff --git a/packages/sandbox-core/test/core/service/remoteDebugService.test.ts b/packages/sandbox-core/test/core/service/remoteDebugService.test.ts index 76de6f8..53bf29d 100644 --- a/packages/sandbox-core/test/core/service/remoteDebugService.test.ts +++ b/packages/sandbox-core/test/core/service/remoteDebugService.test.ts @@ -15,4 +15,24 @@ describe('remoteDebugServiceTest', () => { assert(res.every((d) => d.debugPort && d.webSocketDebuggerUrl && d.token)); }); + it('getDebuggableHost without permission', async () => { + const remoteDebugService = await getInstance('remoteDebugService'); + let throwError = false; + try { + await remoteDebugService.getDebuggableHost({ + scope: 'test', + scopeName: 'noPermission', + uid: '1001', + ip: '127.0.0.1', + }); + } catch (err) { + if (err.message.match(/no permission/)) { + throwError = true; + } else { + throw err; + } + } + assert(throwError); + }); + }); diff --git a/packages/sandbox-core/test/core/service/traceService.test.ts b/packages/sandbox-core/test/core/service/traceService.test.ts index 7a37f73..27f81ec 100644 --- a/packages/sandbox-core/test/core/service/traceService.test.ts +++ b/packages/sandbox-core/test/core/service/traceService.test.ts @@ -10,7 +10,9 @@ describe('traceServiceTest', async () => { const keyTraceModel = await getInstance('keyTraceModel'); await keyTraceModel.bulkCreate(keyTraceMockData); const traceModel = await getInstance('traceModel'); - await traceModel.bulkCreate(traceMockData); + await traceModel.bulkCreate(traceMockData.traces); + const traceNodeModel = await getInstance('traceNodeModel'); + await traceNodeModel.bulkCreate(traceMockData.traceNodes); }); it('listFocusTraces', async () => { @@ -19,18 +21,540 @@ describe('traceServiceTest', async () => { scope: 'test', scopeName: 'sandbox-test', }); - assert(res); + assert(res.data.length === traceMockData.traces.length); }); it('listTraces', async () => { const traceService = await getInstance('traceService'); - const res = await traceService.listTraces({ + let res = await traceService.listTraces({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + env: 'dev', + hostname: 'develop.server', + scopeName: 'sandbox-test', + }); + assert(res.data.length === traceMockData.traces.length); + + res = await traceService.listTraces({ + scope: 'test', + ip: '10.0.0.1', + scopeName: 'sandbox-test', + }); + assert(res.data.length >= 0); + + res = await traceService.listTraces({ + scope: 'test', + scopeName: 'sandbox-test', + }); + assert(res.data.length >= 0); + }); + + it('traceDetail', async () => { + const traceService = await getInstance('traceService'); + const testUUID = '3e351e0f-9abd-4023-8a2a-061dc3cacffc'; + let res = await traceService.traceDetail({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + env: 'dev', + ip: '10.0.0.1', + scopeName: 'sandbox-test', + uuid: testUUID, + }); + assert(res && res.uuid === testUUID); + + res = await traceService.traceDetail({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + uuid: testUUID, + }); + assert(res && res.uuid === testUUID); + }); + + it('toggleTraceFocus', async () => { + const traceService = await getInstance('traceService'); + const res = await traceService.toggleTraceFocus({ + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + focus: 1, + }); + assert(typeof res === 'boolean'); + }); + + it('toggleTraceFocus cancel', async () => { + const traceService = await getInstance('traceService'); + const res = await traceService.toggleTraceFocus({ + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + focus: 0, + }); + assert(typeof res === 'boolean'); + }); + + it('traceTotalitySummary', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.traceTotalitySummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + env: 'dev', + hostname: 'develop.server', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }); + assert(res); + assert(res[0] === traceMockData.traces.reduce((total, trace) => total += trace.traceDuration, 0) / traceMockData.traces.length); + assert(res[1] === traceMockData.traces.length); + assert(res[2] === 100); + + res = await traceService.traceTotalitySummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + ip: '10.0.0.1', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }); + assert(res); + assert(res[0] === traceMockData.traces.reduce((total, trace) => total += trace.traceDuration, 0) / traceMockData.traces.length); + assert(res[1] === traceMockData.traces.length); + assert(res[2] === 100); + + res = await traceService.traceTotalitySummary({ startTime: new Date('2018-09-28 01:00:00'), endTime: new Date('2018-09-28 01:30:00'), scope: 'test', scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', }); assert(res); + assert(res[0] === traceMockData.traces.reduce((total, trace) => total += trace.traceDuration, 0) / traceMockData.traces.length); + assert(res[1] === traceMockData.traces.length); + assert(res[2] === 100); + }); + + it('spanTotalitySummary', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.spanTotalitySummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + }); + assert(res.slice(0, 3).every((val) => typeof val === 'number')); + assert(typeof res[3] === 'string' && res[3].length > 0); + + res = await traceService.spanTotalitySummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + ip: '10.0.0.1', + }); + assert(res.slice(0, 3).every((val) => typeof val === 'number')); + assert(typeof res[3] === 'string' && res[3].length > 0); + + res = await traceService.spanTotalitySummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + }); + assert(res.slice(0, 3).every((val) => typeof val === 'number')); + assert(typeof res[3] === 'string' && res[3].length > 0); + }); + + it('traceSummaryTrend', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.traceSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + env: 'dev', + hostname: 'develop.server', + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length === 1); + assert(res.data.every((record) => { + return record.slice(1, 4).every((val) => typeof val === 'number') + && record[0] instanceof Date; + })); + + res = await traceService.traceSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + ip: '10.0.0.1', + scope: 'test', + scopeName: 'sandbox-test', + }); + assert(res.data.length === 1); + assert(res.data.every((record) => { + return record.slice(1, 4).every((val) => typeof val === 'number') + && record[0] instanceof Date; + })); + + res = await traceService.traceSummaryTrend({ + scope: 'test', + scopeName: 'sandbox-test', + }); + assert(res.data.length === 0); + }); + + it('listTraceByName', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.listTraceByName({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + env: 'dev', + hostname: 'develop.server', + scope: 'test', + scopeName: 'sandbox-test', + }); + assert(res.data.length === traceMockData.traces.length); + + res = await traceService.listTraceByName({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + ip: '10.0.0.1', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length === 1); + + res = await traceService.listTraceByName({ + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length === 0); + }); + + it('traceSummary', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.traceSummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + env: 'dev', + hostname: 'develop.server', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }); + assert(res.every((val) => typeof val === 'number')); + + res = await traceService.traceSummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + ip: '10.0.0.1', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + }); + assert(res.every((val) => typeof val === 'number')); + + res = await traceService.traceSummary({ + scope: 'test', + scopeName: 'sandbox-test-not-exist', + traceName: 'HTTP-GET:/products', + }); + assert(res.every((val) => typeof val === 'number')); + }); + + it('traceNodeSummaryList', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.traceNodeSummaryList({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + env: 'dev', + hostname: 'develop.server', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + focus: 0, + }); + assert(res.data.every((record) => { + return record.slice(0, 3).every((val) => typeof val === 'number') + && typeof record[3] === 'string'; + })); + + res = await traceService.traceNodeSummaryList({ + scope: 'test', + ip: '10.0.0.1', + scopeName: 'sandbox-test', + focus: 0, + }); + assert(res.data.every((record) => { + return record.slice(0, 3).every((val) => typeof val === 'number') + && typeof record[3] === 'string'; + })); + + res = await traceService.traceNodeSummaryList({ + scope: 'test', + scopeName: 'sandbox-test', + traceName: 'HTTP-GET:/products', + focus: 0, + }); + assert(res.data.every((record) => { + return record.slice(0, 3).every((val) => typeof val === 'number') + && typeof record[3] === 'string'; + })); + }); + + it('traceNodeSummary', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.traceNodeSummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.every((val) => typeof val === 'number')); + + res = await traceService.traceNodeSummary({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + ip: '10.0.0.1', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.every((val) => typeof val === 'number')); + + res = await traceService.traceNodeSummary({ + scope: 'test', + scopeName: 'sandbox-test', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.length >= 0); + }); + + it('traceNodeSummaryTrend', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.traceNodeSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length === 1); + assert(res.data.every((record) => { + return record.slice(1, 4).every((val) => typeof val === 'number') + && record[0] instanceof Date; + })); + + res = await traceService.traceNodeSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + ip: '10.0.0.1', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length === 1); + assert(res.data.every((record) => { + return record.slice(1, 4).every((val) => typeof val === 'number') + && record[0] instanceof Date; + })); + + res = await traceService.traceNodeSummaryTrend({ + scope: 'test', + scopeName: 'sandbox-test', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length === 0); + }); + + it('spanTargetList', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.spanTargetList({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length > 0); + assert(res.data.every((val) => typeof val[0] === 'string' && typeof val[1] === 'number')); + + res = await traceService.spanTargetList({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + ip: '10.0.0.1', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + }); + assert(res.data.length > 0); + assert(res.data.every((val) => typeof val[0] === 'string' && typeof val[1] === 'number')); + + res = await traceService.spanTargetList({ + scope: 'test', + scopeName: 'sandbox-test', + spanName: 'configs', + }); + assert(res.data.length === 0); + }); + + it('spanTargetSummaryTrend', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.spanTargetSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.data.length === 1); + assert(res.data.every((record) => { + return record.slice(1, 4).every((val) => typeof val === 'number') + && record[0] instanceof Date; + })); + + res = await traceService.spanTargetSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + ip: '10.0.0.1', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.data.length === 1); + assert(res.data.every((record) => { + return record.slice(1, 4).every((val) => typeof val === 'number') + && record[0] instanceof Date; + })); + + res = await traceService.spanTargetSummaryTrend({ + scope: 'test', + scopeName: 'sandbox-test', + spanName: 'configs', + spanTarget: '/', + }); + assert(res.data.length === 0); + }); + + it('listNodesByTarget', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.listNodesByTarget({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.data.length === 1); + + res = await traceService.listNodesByTarget({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + ip: '10.0.0.1', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.data.length === 1); + + res = await traceService.listNodesByTarget({ + scope: 'test', + scopeName: 'sandbox-test', + spanName: 'configs', + spanTarget: '/', + }); + assert(res.data.length === 0); + }); + + it('spansSummaryTrend', async () => { + const traceService = await getInstance('traceService'); + let res = await traceService.spansSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.types[0] === 'configs'); + assert(Object.keys(res).filter((key) => key !== 'types').every((key) => res[key].every((val) => val.timestamp && val.configs))); + + res = await traceService.spansSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + ip: '10.0.0.1', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.types[0] === 'configs'); + assert(Object.keys(res).filter((key) => key !== 'types').every((key) => res[key].every((val) => val.timestamp && val.configs))); + + res = await traceService.spansSummaryTrend({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + scope: 'test', + scopeName: 'sandbox-test', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.types[0] === 'configs'); + assert(Object.keys(res).filter((key) => key !== 'types').every((key) => res[key].every((val) => val.timestamp && val.configs))); + }); + + it('traceFlowHistogram', async () => { + const traceService = await getInstance('traceService'); + const res = await traceService.traceFlowHistogram({ + startTime: new Date('2018-09-28 01:00:00'), + endTime: new Date('2018-09-28 01:30:00'), + env: 'dev', + scope: 'test', + scopeName: 'sandbox-test', + spanName: 'configs', + traceName: 'HTTP-GET:/products', + spanTarget: '/', + }); + assert(res.data.length === 2); }); after(async () => { @@ -46,7 +570,15 @@ describe('traceServiceTest', async () => { await traceModel.destroy({ where: { uuid: { - [Op.in]: traceMockData.map((tr) => tr.uuid), + [Op.in]: traceMockData.traces.map((tr) => tr.uuid), + }, + }, + }); + const traceNodeModel = await getInstance('traceNodeModel'); + await traceNodeModel.destroy({ + where: { + uuid: { + [Op.in]: traceMockData.traceNodes.map((tr) => tr.uuid), }, }, }); diff --git a/packages/sandbox-core/test/fixtures/config.ts b/packages/sandbox-core/test/fixtures/config.ts index ea224fc..2053c08 100644 --- a/packages/sandbox-core/test/fixtures/config.ts +++ b/packages/sandbox-core/test/fixtures/config.ts @@ -3,7 +3,6 @@ export default { host: '127.0.0.1', username: 'root', port: 3306, - password: '123456', encrypt: false, database: 'sandbox', }, @@ -11,11 +10,17 @@ export default { host: '127.0.0.1', username: 'root', port: 3306, - password: '123456', encrypt: false, database: 'sandbox', }, pandora: { restfulPort: 3010, }, + tsdb: { + host: '127.0.0.1', + port: 4242, + }, + cipher: { + secret: 'midway_sandbox', + }, }; diff --git a/packages/sandbox-core/test/fixtures/injections/privilegeAdapter.ts b/packages/sandbox-core/test/fixtures/injections/privilegeAdapter.ts index 1d23572..2cd6576 100644 --- a/packages/sandbox-core/test/fixtures/injections/privilegeAdapter.ts +++ b/packages/sandbox-core/test/fixtures/injections/privilegeAdapter.ts @@ -3,6 +3,9 @@ import { provide } from 'midway-mirror'; @provide('privilegeAdapter') export class PrivilegeAdapter { async isAppOps(scope: string, scopeName: string, uid: string): Promise { + if (scopeName === 'noPermission') { + return false; + } return true; } } diff --git a/packages/sandbox-core/test/fixtures/mockData/traceMockData.ts b/packages/sandbox-core/test/fixtures/mockData/traceMockData.ts index 720f670..68be9ad 100644 --- a/packages/sandbox-core/test/fixtures/mockData/traceMockData.ts +++ b/packages/sandbox-core/test/fixtures/mockData/traceMockData.ts @@ -1,36 +1,68 @@ -export default [ - { - timestamp: new Date('2018-09-28 01:13:34'), - scope: 'test', - scopeName: 'sandbox-test', - env: 'dev', - hostname: 'develop.server', - ip: '10.0.0.1', - uuid: '0f7ea820-3fb2-4496-b755-ca5bd76763bd', - traceId: '0b859a6d15381252001705791e067a', - version: 1, - traceSpans: '[]', - unix_timestamp: 1538068414, - trace_duration: 3, - pid: 4328, - traceName: 'HTTP-GET:/', - traceStatus: 1, - }, - { - timestamp: new Date('2018-09-28 01:13:35'), - scope: 'test', - scopeName: 'sandbox-test', - env: 'dev', - hostname: 'develop.server', - ip: '10.0.0.1', - uuid: '3e351e0f-9abd-4023-8a2a-061dc3cacffc', - traceId: '0b859a6d153091a2001705791e067a', - version: 1, - traceSpans: '[]', - unix_timestamp: 1538068415, - trace_duration: 2, - pid: 4928, - traceName: 'HTTP-GET:/products', - traceStatus: 1, - }, -]; +export default { + traces: [ + { + timestamp: new Date('2018-09-28 01:13:34'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + ip: '10.0.0.1', + uuid: '0f7ea820-3fb2-4496-b755-ca5bd76763bd', + traceId: '0b859a6d15381252001705791e067a', + version: 1, + traceSpans: '[]', + unixTimestamp: 1538068414, + traceDuration: 3, + pid: 4328, + traceName: 'HTTP-GET:/', + traceStatus: 1, + }, + { + timestamp: new Date('2018-09-28 01:13:35'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + ip: '10.0.0.1', + uuid: '3e351e0f-9abd-4023-8a2a-061dc3cacffc', + traceId: '0b859a6d153091a2001705791e067a', + version: 1, + traceSpans: '[]', + unixTimestamp: 1538068415, + traceDuration: 2, + pid: 4928, + traceName: 'HTTP-GET:/products', + traceStatus: 1, + }, + ], + traceNodes: [ + { + timestamp: new Date('2018-09-28 01:13:35'), + scope: 'test', + scopeName: 'sandbox-test', + env: 'dev', + hostname: 'develop.server', + ip: '10.0.0.1', + uuid: '3e351e0f-9abd-4023-8a2a-061dd3cacffc', + traceId: '0b859a6d153091a2001705791e067a', + version: 1, + traceSpans: '[]', + unixTimestamp: 1538068415, + traceDuration: 2, + traceName: 'HTTP-GET:/products', + traceStatus: 1, + spanName: 'configs', + spanDuration: 142, + spanType: 0, + spanTags: '{}', + spanId: 'eb26f0605ab77a93', + spanRpcId: '0.1.1.0', + spanCode: 200, + spanError: 0, + spanMethod: 'GET', + spanTimestamp: '2018-09-28 01:13:35', + pid: 2045, + spanTarget: '/', + }, + ], +}; diff --git a/packages/sandbox-mvp/package.json b/packages/sandbox-mvp/package.json index 702ee08..086aa32 100755 --- a/packages/sandbox-mvp/package.json +++ b/packages/sandbox-mvp/package.json @@ -1,12 +1,12 @@ { "name": "sandbox-mvp", - "version": "0.0.1", + "version": "0.0.2", "description": "MVP version of sandbox", "dependencies": { "chrome-devtools-frontend": "^1.0.590489", "egg-view-nunjucks": "^2.2.0", - "midway": "^0.3.7", - "sandbox-core": "^0.0.1" + "midway": "^0.4.0", + "sandbox-core": "^0.0.2" }, "devDependencies": { "@types/mocha": "^5.2.5", diff --git a/packages/sandbox-mvp/src/app.ts b/packages/sandbox-mvp/src/app.ts index f118948..de73773 100644 --- a/packages/sandbox-mvp/src/app.ts +++ b/packages/sandbox-mvp/src/app.ts @@ -1,12 +1,13 @@ import { dirname } from 'path'; import staticCache = require('koa-static-cache'); import { Application } from 'midway'; -import { DebugServer } from 'sandbox-core'; export = (app: Application) => { app.on('server', (server) => { - const debugServer = new DebugServer(server); - debugServer.start(); + app.applicationContext.getAsync('debugServer').then((debugServer) => { + debugServer.setServer(server); + debugServer.start(); + }); }); app.use(staticCache({ dir: dirname(require.resolve('chrome-devtools-frontend/front_end/inspector.html')), diff --git a/packages/sandbox-mvp/src/app/middleware/assets.ts b/packages/sandbox-mvp/src/app/middleware/assets.ts index 742e746..6806eb8 100644 --- a/packages/sandbox-mvp/src/app/middleware/assets.ts +++ b/packages/sandbox-mvp/src/app/middleware/assets.ts @@ -1,6 +1,6 @@ export default function assets(options, app) { return async (ctx, next) => { - ctx.locals.publicPath = '//g.alicdn.com/midway/sandbox-newui/0.0.5/'; + ctx.locals.publicPath = '//g.alicdn.com/midway/sandbox-newui/0.0.7/'; ctx.locals.env = 'prod'; await next(); }; diff --git a/packages/sandbox-mvp/src/config/config.default.ts b/packages/sandbox-mvp/src/config/config.default.ts index c93779d..9a5d072 100644 --- a/packages/sandbox-mvp/src/config/config.default.ts +++ b/packages/sandbox-mvp/src/config/config.default.ts @@ -14,7 +14,7 @@ module.exports = appInfo => { }; config.pandora = { - restfulPort: 9081 + restfulPort: 7002 }; config.tsdb = { @@ -22,7 +22,7 @@ module.exports = appInfo => { port: 4242 }; - config.histore = { + config.dw = { host: process.env.UNDER_DOCKER ? 'mariadb-columnstore' : '127.0.0.1', port: 3306, username: 'sandbox', @@ -30,7 +30,7 @@ module.exports = appInfo => { database: 'column_sandbox', }; - config.mysql = { + config.coreDB = { host: process.env.UNDER_DOCKER ? 'mariadb-columnstore' : '127.0.0.1', port: 3306, username: 'sandbox', @@ -86,11 +86,11 @@ module.exports = appInfo => { }; config.customLogger = { - historeLogger: { - file: path.join(appInfo.root, `logs/sandbox-datasource-histore.log`) + dwLogger: { + file: path.join(appInfo.root, `logs/sandbox-datasource-dw.log`) }, - mysqlLogger: { - file: path.join(appInfo.root, `logs/sandbox-datasource-mysql.log`) + coreDBLogger: { + file: path.join(appInfo.root, `logs/sandbox-datasource-coredb.log`) } }; diff --git a/packages/sandbox-mvp/src/config/metrics.ts b/packages/sandbox-mvp/src/config/metrics.ts index 16024c6..0691ce7 100644 --- a/packages/sandbox-mvp/src/config/metrics.ts +++ b/packages/sandbox-mvp/src/config/metrics.ts @@ -5,8 +5,9 @@ import {focusLayout} from './metricsLayouts/focusLayout'; export const coreMetrics = { cpuUsage: { aggregator: 'avg', - metric: 'system.tsar.cpu', + metric: 'system.cpu.usage', affix: '%', + normalizedValue: true, }, load1: { aggregator: 'avg', @@ -14,13 +15,15 @@ export const coreMetrics = { }, memUsage: { aggregator: 'avg', - metric: 'system.tsar.mem', + metric: 'system.mem.usage', affix: '%', + normalizedValue: true, }, diskUsage: { aggregator: 'avg', - metric: 'system.tsar.df', + metric: 'system.disk.partition.used_ratio', affix: '%', + normalizedValue: true, }, qps: { aggregator: 'sum', diff --git a/packages/sandbox-mvp/src/config/metricsLayouts/focusLayout.ts b/packages/sandbox-mvp/src/config/metricsLayouts/focusLayout.ts index abb92a4..65328c3 100644 --- a/packages/sandbox-mvp/src/config/metricsLayouts/focusLayout.ts +++ b/packages/sandbox-mvp/src/config/metricsLayouts/focusLayout.ts @@ -47,21 +47,18 @@ export const focusLayout = [{ aggregator: 'avg', metric: 'system.load.1min', title: 'Load 1', - type: 'number', }, { aggregator: 'avg', metric: 'system.load.5min', title: 'Load 5', - type: 'number', }, { aggregator: 'avg', metric: 'system.load.15min', title: 'Load 15', - type: 'number', }, ], @@ -73,7 +70,6 @@ export const focusLayout = [{ aggregator: 'sum', metric: 'error.all.bucket_count', title: '错误数量', - type: 'number', unit: '条', }, @@ -84,11 +80,10 @@ export const focusLayout = [{ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.cpu', + metric: 'system.cpu.usage', title: 'CPU 使用率', - type: 'percent', - normalizedValue: false, + normalizedValue: true, }, ], }, @@ -97,11 +92,10 @@ export const focusLayout = [{ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.mem', + metric: 'system.mem.usage', title: '内存使用率', - type: 'percent', - normalizedValue: false, + normalizedValue: true, }, ], }, @@ -110,11 +104,10 @@ export const focusLayout = [{ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.df', + metric: 'system.disk.partition.used_ratio', title: '磁盘占用率', - type: 'percent', - normalizedValue: false, + normalizedValue: true, }, ], }, @@ -126,7 +119,7 @@ export const focusLayout = [{ { type: 'number', aggregator: 'sum', - metric: 'system.tsar.ifin', + metric: 'system.nettraffic.eth0.net.in.bytes', unit: 'Bytes/ms', title: 'eth0 流入', @@ -134,7 +127,7 @@ export const focusLayout = [{ { type: 'number', aggregator: 'sum', - metric: 'system.tsar.ifout', + metric: 'system.nettraffic.eth0.net.out.bytes', unit: 'Bytes/ms', title: 'eth0 流出', @@ -146,7 +139,7 @@ export const focusLayout = [{ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.tcp_retry', + metric: 'system.tcp.retry.rate', title: '重试率', type: 'percent', diff --git a/packages/sandbox-mvp/src/config/metricsLayouts/systemLayout.ts b/packages/sandbox-mvp/src/config/metricsLayouts/systemLayout.ts index b0591ba..b62b725 100644 --- a/packages/sandbox-mvp/src/config/metricsLayouts/systemLayout.ts +++ b/packages/sandbox-mvp/src/config/metricsLayouts/systemLayout.ts @@ -40,10 +40,10 @@ export const systemLayout = [ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.cpu', + metric: 'system.cpu.usage', title: 'CPU 使用率', type: 'percent', - normalizedValue: false, + normalizedValue: true, }, ], }, @@ -52,10 +52,10 @@ export const systemLayout = [ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.mem', + metric: 'system.mem.usage', title: '内存使用率', type: 'percent', - normalizedValue: false, + normalizedValue: true, }, ], }, @@ -64,10 +64,10 @@ export const systemLayout = [ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.df', + metric: 'system.disk.partition.used_ratio', title: '磁盘占用率', type: 'percent', - normalizedValue: false, + normalizedValue: true, }, ], }, @@ -77,7 +77,7 @@ export const systemLayout = [ { type: 'number', aggregator: 'sum', - metric: 'system.tsar.ifin', + metric: 'system.nettraffic.eth0.net.in.bytes', unit: 'Bytes/ms', title: 'eth0 流入', }, @@ -89,7 +89,7 @@ export const systemLayout = [ { type: 'number', aggregator: 'sum', - metric: 'system.tsar.ifout', + metric: 'system.nettraffic.eth0.net.out.bytes', unit: 'Bytes/ms', title: 'eth0 流出', }, @@ -101,7 +101,7 @@ export const systemLayout = [ { type: 'number', aggregator: 'sum', - metric: 'system.tsar.pktin', + metric: 'system.nettraffic.eth0.net.in.packets', unit: '', title: '入包', }, @@ -113,7 +113,7 @@ export const systemLayout = [ { type: 'number', aggregator: 'sum', - metric: 'system.tsar.pktout', + metric: 'system.nettraffic.eth0.net.out.packets', unit: '', title: '出包', }, @@ -124,7 +124,7 @@ export const systemLayout = [ indicators: [ { aggregator: 'avg', - metric: 'system.tsar.tcp_retry', + metric: 'system.tcp.retry.rate', title: '重试率', type: 'percent', normalizedValue: false, diff --git a/packages/sandbox-mvp/test/app/controller/applicationCtrl.test.ts b/packages/sandbox-mvp/test/app/controller/applicationCtrl.test.ts new file mode 100644 index 0000000..63cd3ed --- /dev/null +++ b/packages/sandbox-mvp/test/app/controller/applicationCtrl.test.ts @@ -0,0 +1,9 @@ +import {ApplicationCtrl} from '../../../src/app/controller/applicationCtrl'; +import * as core from 'sandbox-core'; +import * as assert from 'assert'; +describe('applicationCtrl', () => { + it('should inherit from sandbox-core', () => { + const myApplicationCtrl = new ApplicationCtrl(); + assert(myApplicationCtrl instanceof core.ApplicationCtrl); + }); +}); diff --git a/readme.md b/readme.md index 808a617..5e3d51f 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ ## Sandbox -Preparing... +Preparing.... diff --git a/scripts/cov.sh b/scripts/cov.sh new file mode 100644 index 0000000..f416a70 --- /dev/null +++ b/scripts/cov.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +cwd=`pwd` +lerna run cov +rm -rf "${cwd}/.nyc_output" || true +mkdir "${cwd}/.nyc_output" +cp -r ./packages/*/.nyc_output/* $cwd/.nyc_output/ || true +cp -r ./packages/*/node_modules/.nyc_output/* $cwd/.nyc_output/ || true +./node_modules/.bin/nyc report