Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui update #99

Merged
merged 5 commits into from Aug 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -11,3 +11,5 @@ log.txt
logger.log
tmp
data/rs.csv
caliper-workspace/
caliper.log
116 changes: 66 additions & 50 deletions README.MD
@@ -1,13 +1,19 @@
# Probe

[![Build Status](https://dev.azure.com/yy19902439/yy19902439/_apis/build/status/SamYuan1990.Probe?branchName=main)](https://dev.azure.com/yy19902439/yy19902439/_build/latest?definitionId=8&branchName=main)

[![Issues](https://img.shields.io/github/issues/SamYuan1990/Probe?color=0088ff)](https://github.com/SamYuan1990/Probe/issues)

[![GitHub pull requests](https://img.shields.io/github/issues-pr/SamYuan1990/Probe?color=0088ff)](https://github.com/SamYuan1990/Probe/pulls)

[中文](README_ZH.MD)


## What is Probe
![Probe](doc/Probe.png)
According to [blockchain-performance-metrics](https://www.hyperledger.org/learn/publications/blockchain-performance-metrics), Probe is a web GUI application for Hyperledger Fabric mantianer, user, research. Recently, aims at providing a way to control both SUT and LGC to find the best block config logic for specific chaincode for specific fabric network. Meanwhile has a better understanding of how block config impacts performance.

![Probe](/doc/Probe.png)

According to [blockchain-performance-metrics](https://www.hyperledger.org/learn/publications/blockchain-performance-metrics), Probe is a web GUI application for Hyperledger Fabric mantianer, user, research. Recently, aims at providing a way to control both SUT and LGC to find the best block config logic for specific chaincode for specific fabric network. Meanwhile has a better understanding of how block config impacts performance.

- Probe provides loop test control for given block parameter arrays.
- Probe provides TPS result review via GUI.
Expand All @@ -18,74 +24,84 @@ Long term goal for Probe is a coordinator between Test Harness or LGC, SUT.
- Probe will allow you design shell scripts to schedule SUT and Test Harness.
- Probe will allow you investigate performance matrix with GUI in customer way.

## You can use Probe to ...
- [HowToConfigFabricParameters](doc/HowToConfigFabricParameters.md)
**You can use Probe to ...**[HowToConfigFabricParameters](doc/HowToConfigFabricParameters.md)

## Why Probe
As discussed with [TWGC performance work group](https://github.com/Hyperledger-TWGC/fabric-performance-wiki), we found out that different block parameters, networks, chaincode language and chaincode logic having influence final TPS.
To answer, the best parameter for specific fabric network and fabric chaincode, this project been created.

## Probe is not
- Real time time monitor, for real time tps monitor, pls use Prometheus. (But Probe has demo for it with test network [here](https://www.bilibili.com/video/BV1x54y1x78Z))
- Auto test framework for Fabric performance, as in probe, we will invoke as byfn or minifab for your network up/down/cleanup.
- Performance test tool for Fabric, for this we using tape.
- GUI for tape, tape focus on once off time performance testing.
---
**Sample run of [Probe](https://www.bilibili.com/video/BV1Kz4y1179L)**

## Quick start
1. Install this project `npm install`
---

1. Install fabric-sample environment
## Table Of Content

`curl -vsS https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash`
* [Prerequisites](#prerequisites)
* [Quick_Start](#Quick_Start)
* [Contributing](#contributing)
* [License](#license)
* [Contact](#contact)
* [Regards](#thanks-for-choosing)

**Note**
---
## Prerequisites
1. Install this project `npm install`
1. Install fabric-sample environment
`curl -vsS https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash`
**Note**
If the above curl command fails, it may be that the old version of curl cannot handle redirection or cannot be redirected due to network reasons in

If the above curl command fails, it may be that the old version of curl cannot handle redirection or cannot be redirected due to network reasons in
some countries and regions. At this time, users can download the [bootstrap.sh](https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh) script then run it.

1. Get tape `docker pull guoger/tape`

1. Apply the bridge file to adjust block parameters for test network `cp sample/prepareConfig.sh fabric-samples/test-network`

1. `npm start`

1. Access localhost:3000, click ![TestNetworkSample](doc/quick_sample.png)
---

1. Click![submit](doc/quicksample2.png)
## Quick_Start

1. Access localhost:3000, click ![TestNetworkSample](doc/quick_sample.png)
1. Click![submit](doc/quicksample2.png)
1. Access `localhost:3000/result/BatchTimeout` to see TPS relationship with BatchTimeout

1. Access `localhost:3000/result/MaxMessageCount` to see TPS relationship with MaxMessageCount

## Version Plan
version | define| feature
---|---|---
0.0.4 | customer UI enhancement | allow user chose parameters to show on UI
0.0.5 | support different deploy plan with peers | 4/5 6/3 8/1
0.0.6 | support different deploy plan with orgs | 2 3 4
0.0.7 | support different deploy plan with gossip | 1:1 1:2 1:3
0.0.8 | support different deploy plan with mvcc | 10 20 40
0.0.9 | support different deploy plan with data size | 10k 512k 1M
1.0.0 | fix up bugs after 0.0.4 |
1.1.x | tools supporting | supports caliper
1.2.x | network starter supporting | supports cello

# How to contribute
---
## Contributing
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.

If your want to contribute Probe with new feature, bug fixing please create a new issue, of course with PR is best.
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -s`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

If your want to contribute Probe with new feature, bug fixing please create a new issue, of course with PR is best.
Also welcome for documentatoin, learning course, etc.

For development, please complete `Quick start` above.

For Frontend, please use `npm run build`.

For backend, please develop `--DryRun` as mock for unit test and adding real cases in CI

## Video (in Chinese)
version | URL | comments
---|---|---
0.0.1 | https://www.bilibili.com/video/BV1x54y1x78Z | N/A
0.0.1 | https://www.bilibili.com/video/BV1dV411y7oZ | N/A
0.0.2 | https://www.bilibili.com/video/bv13t4y1B7AE | N/A
0.0.3 | https://www.bilibili.com/video/BV1Kz4y1179L | N/A
---
## License
Hyperledger Project source code files are made available under the Apache License, Version 2.0 (Apache-2.0), located in the [LICENSE](LICENSE) file.

---
## Contact

* [Maintainers](MAINTAINERS.md)

---

## Why Probe

As discussed with [TWGC performance work group](https://github.com/Hyperledger-TWGC/fabric-performance-wiki), we found out that different block parameters, networks, chaincode language and chaincode logic having influence final TPS.

To answer, the best parameter for specific fabric network and fabric chaincode, this project been created.

## Probe is not

- Real time time monitor, for real time tps monitor, pls use Prometheus. (But Probe has demo for it with test network [here](https://www.bilibili.com/video/BV1x54y1x78Z))
- Auto test framework for Fabric performance, as in probe, we will invoke as byfn or minifab for your network up/down/cleanup.
- Performance test tool for Fabric, for this we using tape.
- GUI for tape, tape focus on once off time performance testing.


### THANKS FOR CHOOSING

17 changes: 17 additions & 0 deletions lib/commands.js
Expand Up @@ -21,6 +21,23 @@ exports.newVersionCommand = function newVersionCommand(cmd, thePath, dryRun,
}
if (cmd.cmdType === 'Tape') {
command.tps = true;
command.cmdType = 'Tape';
let vmount = false;
for (let i = 1; i < cmd.args.length; i++) {
command.args[i - 1] = cmd.args[i];
if (vmount) {
const arr = cmd.args[i].split(':');
command.args[i - 1] = path.resolve(arr[0]) + ':' + arr[1];
vmount = false;
}
if (cmd.args[i] === '-v') {
vmount = true;
}
}
}
if (cmd.cmdType === 'Caliper') {
command.tps = true;
command.cmdType = 'Caliper';
let vmount = false;
for (let i = 1; i < cmd.args.length; i++) {
command.args[i - 1] = cmd.args[i];
Expand Down
24 changes: 20 additions & 4 deletions lib/libs.js
Expand Up @@ -8,11 +8,11 @@ exports.handleStatus = function handleStatus(rs) {
if (rs.status !== 0) {
if (rs.stderr) {
logger.error(rs.stderr.toString('utf-8'));
console.log(rs.stderr.toString('utf-8'));
// console.log(rs.stderr.toString('utf-8'));
}
if (rs.output) {
logger.error(rs.output.toString('utf-8'));
console.log(rs.output.toString('utf-8'));
// console.log(rs.output.toString('utf-8'));
}
if (!rs.stderr && !rs.output) {
logger.error(JSON.stringify(rs));
Expand All @@ -30,10 +30,18 @@ exports.executeCommand = function executeCommand(command) {
}
const rs = process.spawnSync(command.command, command.args, command.config);
if (command.tps) {
logger.info('debugging');
logger.info(command);
logger.info('debugging');
if (rs.status !== 0) {
return this.handleStatus(rs);
}
return this.TapeTpsFilter(rs);
if (command.cmdType === 'Tape') {
return this.TapeTpsFilter(rs);
}
if (command.cmdType === 'Caliper') {
return this.CaliperTpsFilter(rs);
}
} else {
return this.handleStatus(rs);
}
Expand All @@ -48,6 +56,14 @@ exports.TapeTpsFilter = function TapeTpsFilter(rs) {
return str;
};

exports.CaliperTpsFilter = function CaliperTpsFilter(rs) {
logger.info(rs.output.toString('utf-8'));
const str = rs.output.toString('utf-8', 0);
const reg_str = str.match(/\|.*\|/g);
const arr = reg_str.toString().split('|');
return arr[arr.length - 2];
};

exports.RunNew = function RunNew(BatchTimeout, MaxMessageCount, AbsoluteMaxBytes, PreferredMaxBytes, dryRun, cmdPath, cmds) {
let status = 0;
logger.info(dryRun);
Expand All @@ -64,7 +80,7 @@ exports.RunNew = function RunNew(BatchTimeout, MaxMessageCount, AbsoluteMaxBytes
logger.info(PreferredMaxBytesElement);
const command = libcommands.newVersionCommand(cmd, cmdPath, dryRun,
BatchTimeoutElement, MaxMessageCountElement, AbsoluteMaxBytesElement, PreferredMaxBytesElement);
console.log(command);
// console.log(command);
if (!command.tps) {
status = this.executeCommand(command);
if (status !== 0) {
Expand Down
4 changes: 2 additions & 2 deletions public/javascripts/index/bundle.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions public/javascripts/newUI/bundle.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions public/javascripts/sidebar/bundle.js

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions sample/caliper/myAssetBenchmark.yaml
@@ -0,0 +1,19 @@
test:
name: basic-contract-benchmark
description: test benchmark
workers:
type: local
number: 2
rounds:
- label: readAsset
description: Read asset benchmark
txDuration: 30
rateControl:
type: fixed-load
opts:
transactionLoad: 2
workload:
module: readAsset.js
arguments:
assets: 10
contractId: basic
23 changes: 23 additions & 0 deletions sample/caliper/networkConfig.yaml
@@ -0,0 +1,23 @@
name: Caliper test
version: "2.0.0"

caliper:
blockchain: fabric

channels:
- channelName: mychannel
contracts:
- id: basic

organizations:
- mspid: Org1MSP
identities:
certificates:
- name: 'User1'
clientPrivateKey:
path: '../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk'
clientSignedCert:
path: '../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem'
connectionProfile:
path: '../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/connection-org1.yaml'
discover: true
62 changes: 62 additions & 0 deletions sample/caliper/readAsset.js
@@ -0,0 +1,62 @@
'use strict';

const { WorkloadModuleBase } = require('@hyperledger/caliper-core');

class MyWorkload extends WorkloadModuleBase {
constructor() {
super();
}

async initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext) {
await super.initializeWorkloadModule(workerIndex, totalWorkers, roundIndex, roundArguments, sutAdapter, sutContext);

for (let i=0; i<this.roundArguments.assets; i++) {
const assetID = `${this.workerIndex}_${i}`;
console.log(`Worker ${this.workerIndex}: Creating asset ${assetID}`);
const request = {
contractId: this.roundArguments.contractId,
contractFunction: 'CreateAsset',
invokerIdentity: 'User1',
contractArguments: [assetID,'blue','20','penguin','500'],
readOnly: false
};

await this.sutAdapter.sendRequests(request);
}
}

async submitTransaction() {
const randomId = Math.floor(Math.random()*this.roundArguments.assets);
const myArgs = {
contractId: this.roundArguments.contractId,
contractFunction: 'ReadAsset',
invokerIdentity: 'User1',
contractArguments: [`${this.workerIndex}_${randomId}`],
readOnly: true
};

await this.sutAdapter.sendRequests(myArgs);
}

async cleanupWorkloadModule() {
for (let i=0; i<this.roundArguments.assets; i++) {
const assetID = `${this.workerIndex}_${i}`;
console.log(`Worker ${this.workerIndex}: Deleting asset ${assetID}`);
const request = {
contractId: this.roundArguments.contractId,
contractFunction: 'DeleteAsset',
invokerIdentity: 'User1',
contractArguments: [assetID],
readOnly: false
};

await this.sutAdapter.sendRequests(request);
}
}
}

function createWorkloadModule() {
return new MyWorkload();
}

module.exports.createWorkloadModule = createWorkloadModule;
1 change: 1 addition & 0 deletions src/newUI/App.jsx
Expand Up @@ -17,6 +17,7 @@ function render(){
ApplyTestNetwork = {() => store.dispatch({ type: 'TEST_NET_SAMPLE' })}
ApplyTestNetworkWithMonitor = {() => store.dispatch({ type: 'TEST_NET_MONITOR_SAMPLE' })}
ApplyTestNetworkMinifab = {() => store.dispatch({ type: 'TEST_NET_MINIFAB' })}
ApplyTestNetworkCaliper = {() => store.dispatch({ type: 'TEST_NET_CALIPER' })}
dispatch = {store.dispatch}
/>
,rootEl);
Expand Down
11 changes: 11 additions & 0 deletions src/newUI/components/MyInput.jsx
Expand Up @@ -11,6 +11,7 @@ class MyInput extends React.Component {
super(props);
this.Debug =this.Debug.bind(this);
this.TapeType = this.TapeType.bind(this);
this.CaliperType = this.CaliperType.bind(this);
this.ShellType = this.ShellType.bind(this);
this.AddItem = this.AddItem.bind(this);
this.RemoveItem = this.RemoveItem.bind(this);
Expand All @@ -36,6 +37,15 @@ class MyInput extends React.Component {
)
}

CaliperType(event){
this.props.dispatch(
({
type: 'TYPE_CALIPER',
order: this.props.data.order,
})
)
}

PrePare(event){
this.props.dispatch(
({
Expand Down Expand Up @@ -90,6 +100,7 @@ class MyInput extends React.Component {
>
<Dropdown.Item as="button" onClick={this.ShellType}>Shell</Dropdown.Item>
<Dropdown.Item as="button" onClick={this.TapeType}>Tape</Dropdown.Item>
<Dropdown.Item as="button" onClick={this.CaliperType}>Caliper</Dropdown.Item>
<Dropdown.Item as="button" onClick={this.PrePare}>PrePare</Dropdown.Item>
</DropdownButton>
<ListGroup.Item>{this.props.data.cmdType}</ListGroup.Item>
Expand Down