mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
make error propagation modal
This commit is contained in:
parent
4c940ec73b
commit
428ffe718f
@ -78,7 +78,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
commitWorkspace: function ({$store}) {
|
commitWorkspace: function ({$store}) {
|
||||||
console.log("commit:" + JSON.stringify(this.new_workspace));
|
// console.log("commit:" + JSON.stringify(this.new_workspace));
|
||||||
this.$store.dispatch("workspaces/activateWorkspace", this.new_workspace);
|
this.$store.dispatch("workspaces/activateWorkspace", this.new_workspace);
|
||||||
this.new_workspace = "";
|
this.new_workspace = "";
|
||||||
this.mode = "showing";
|
this.mode = "showing";
|
||||||
|
@ -45,7 +45,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let result={namespaces: collated};
|
let result={namespaces: collated};
|
||||||
console.log("namespaces result:"+JSON.stringify(result));
|
// console.log("namespaces result:"+JSON.stringify(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"author": "Sebastian Estevez & Jonathan Shook",
|
"author": "Sebastian Estevez & Jonathan Shook",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nuxt -c nuxt.config.dev.js",
|
"dev": "nuxt -c nuxt.config.dev.js --port 3003",
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
"start": "nuxt start",
|
"start": "nuxt start",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
<v-app>
|
<v-app>
|
||||||
<main-app-bar>NoSQLBench - Workload Builder</main-app-bar>
|
<main-app-bar>NoSQLBench - Workload Builder</main-app-bar>
|
||||||
|
|
||||||
<v-layout
|
<v-layout>
|
||||||
justify-center
|
|
||||||
align-center>
|
|
||||||
|
|
||||||
<v-main>
|
<v-main>
|
||||||
<v-container fluid>
|
<v-container fluid>
|
||||||
@ -62,9 +60,9 @@ import {saveAs} from "file-saver";
|
|||||||
import yamlDumper from "js-yaml";
|
import yamlDumper from "js-yaml";
|
||||||
import CQL3Parser from '@/antlr/CQL3Parser.js';
|
import CQL3Parser from '@/antlr/CQL3Parser.js';
|
||||||
import CQL3Lexer from '@/antlr/CQL3Lexer.js';
|
import CQL3Lexer from '@/antlr/CQL3Lexer.js';
|
||||||
import defaultYaml from '~/assets/default.yaml';
|
import defaultYaml from 'assets/default.yaml';
|
||||||
import basictypes from '@/assets/basictypes.yaml';
|
import basictypes from 'assets/basictypes.yaml';
|
||||||
import WorkspaceSelector from "~/components/WorkspaceSelector";
|
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
||||||
import AppSelector from "@/components/AppSelector";
|
import AppSelector from "@/components/AppSelector";
|
||||||
import MainAppBar from "@/components/MainAppBar";
|
import MainAppBar from "@/components/MainAppBar";
|
||||||
|
|
322
docsys/src/main/node/docsys/pages/ui/run.vue
Normal file
322
docsys/src/main/node/docsys/pages/ui/run.vue
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
<template>
|
||||||
|
<v-app>
|
||||||
|
<main-app-bar>NoSQLBench - Workload Executor</main-app-bar>
|
||||||
|
<v-container class="d-flex justify-center">
|
||||||
|
|
||||||
|
<v-main>
|
||||||
|
<v-row fluid class="d-flex">
|
||||||
|
<v-col cols="12" fluid class="d-flex justify-space-between justify-center">
|
||||||
|
|
||||||
|
<!-- <v-btn-toggle max="1" v-model="toggle_workspaces" @change="validateAndSearch()">-->
|
||||||
|
|
||||||
|
<!-- <v-btn :disabled="this.toggle_builtins===undefined && this.toggle_workspaces===0">-->
|
||||||
|
<!-- <v-container fluid class="d-flex">-->
|
||||||
|
<!-- <v-icon title="'include ' + workspace">mdi-folder-star</v-icon>-->
|
||||||
|
<!-- <div class="ma-2">workspace '{{ workspace }}'</div>-->
|
||||||
|
<!-- <v-icon v-if="this.toggle_workspaces===0">mdi-check</v-icon>-->
|
||||||
|
<!-- </v-container>-->
|
||||||
|
<!-- </v-btn>-->
|
||||||
|
|
||||||
|
<!-- <v-btn :disabled="this.toggle_builtins===undefined && this.toggle_workspaces===1">-->
|
||||||
|
<!-- <v-container fluid class="d-flex">-->
|
||||||
|
<!-- <v-icon title="search workspaces">mdi-folder-star-multiple</v-icon>-->
|
||||||
|
<!-- <div class="ma-2">all workspaces</div>-->
|
||||||
|
<!-- <v-icon v-if="this.toggle_workspaces===1">mdi-check</v-icon>-->
|
||||||
|
<!-- </v-container>-->
|
||||||
|
<!-- </v-btn>-->
|
||||||
|
<!-- </v-btn-toggle>-->
|
||||||
|
|
||||||
|
<v-btn-toggle v-model="toggle_builtins" @change="validateAndSearch()">
|
||||||
|
<v-btn :disabled="this.toggle_workspaces===undefined">
|
||||||
|
<v-container fluid class="d-flex">
|
||||||
|
<v-icon title="include built-in workloads">mdi-folder-open</v-icon>
|
||||||
|
<div class="ma-2">bundled</div>
|
||||||
|
<v-icon v-if="this.toggle_builtins===0">mdi-check</v-icon>
|
||||||
|
|
||||||
|
</v-container>
|
||||||
|
</v-btn>
|
||||||
|
</v-btn-toggle>
|
||||||
|
|
||||||
|
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row fluid v-if="workloads!==undefined">
|
||||||
|
|
||||||
|
<!-- :item-text="workspace"-->
|
||||||
|
<!-- :item-value="workloadName"-->
|
||||||
|
<!-- v-model="workloadName"-->
|
||||||
|
<v-select
|
||||||
|
:items="availableWorkloads"
|
||||||
|
item-text="workloadName"
|
||||||
|
item-value="workloadName"
|
||||||
|
v-model="selected"
|
||||||
|
v-on:change="loadTemplates()"
|
||||||
|
label="Workload"
|
||||||
|
></v-select>
|
||||||
|
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<!-- TEMPLATES -->
|
||||||
|
|
||||||
|
<v-main justify-start align-start class="d-inline-block pa-4 ma-10">
|
||||||
|
<v-row no-gutters v-if="templates">
|
||||||
|
<v-card v-for="(item, j) in Object.keys(templateparams)"
|
||||||
|
:key="item"
|
||||||
|
class="ma-4 pa-4"
|
||||||
|
>
|
||||||
|
<!-- <v-card-title>{{item}}</v-card-title>-->
|
||||||
|
<v-card-title class="ma-0 pa-0">{{ item }}</v-card-title>
|
||||||
|
<v-text-field hide-details v-model="templateparams[item]" align="center"></v-text-field>
|
||||||
|
<!-- <v-card-title>{{ this.workloadName }}</v-card-title>-->
|
||||||
|
<!-- <v-row v-for="(item, j) in Object.keys(templates)" :key="item.command">-->
|
||||||
|
<!-- <v-text-field v-model="templates[item]" :label="item">{{ item.name }}></v-text-field>-->
|
||||||
|
<!-- </v-row>-->
|
||||||
|
</v-card>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<!-- <v-row v-if="templates">-->
|
||||||
|
<!-- <v-col>-->
|
||||||
|
<!-- <v-card>-->
|
||||||
|
<!-- <v-card-title>{{ this.workloadName }}</v-card-title>-->
|
||||||
|
<!-- <v-row v-for="(item, j) in Object.keys(templates)" :key="item.command">-->
|
||||||
|
<!-- <v-text-field v-model="templates[item]" :label="item">{{ item.name }}></v-text-field>-->
|
||||||
|
<!-- </v-row>-->
|
||||||
|
<!-- </v-card>-->
|
||||||
|
<!-- </v-col>-->
|
||||||
|
<!-- </v-row>-->
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-col></v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12">
|
||||||
|
<v-btn :title="runtitle" v-if="this.selected" v-on:click="runWorkload()">{{ runin }}</v-btn>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
</v-main>
|
||||||
|
|
||||||
|
</v-main>
|
||||||
|
</v-container>
|
||||||
|
|
||||||
|
<v-footer app>
|
||||||
|
<span>© 2020</span>
|
||||||
|
</v-footer>
|
||||||
|
|
||||||
|
</v-app>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
||||||
|
import AppSelector from "@/components/AppSelector";
|
||||||
|
import MainAppBar from "@/components/MainAppBar";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'app-run',
|
||||||
|
components: {
|
||||||
|
AppSelector,
|
||||||
|
WorkspaceSelector,
|
||||||
|
MainAppBar
|
||||||
|
},
|
||||||
|
data(context) {
|
||||||
|
let data = {
|
||||||
|
extraparams: {},
|
||||||
|
templateparams: {},
|
||||||
|
availableWorkloads: [],
|
||||||
|
enabled: false,
|
||||||
|
selected: null,
|
||||||
|
toggle_builtins: false,
|
||||||
|
toggle_workspaces: 0,
|
||||||
|
workspace_names: ['current', 'all'],
|
||||||
|
sample: {
|
||||||
|
"workspace": "default",
|
||||||
|
"yamlPath": "test1.yaml",
|
||||||
|
"scenarioNames": [
|
||||||
|
"default",
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"templates": {
|
||||||
|
"keyspace": "a",
|
||||||
|
"main-cycles": "10000000",
|
||||||
|
"rampup-cycles": "10000000",
|
||||||
|
"read_cl": "LOCAL_QUORUM",
|
||||||
|
"read_partition_ratio": "1",
|
||||||
|
"read_row_ratio": "1",
|
||||||
|
"write_cl": "LOCAL_QUORUM",
|
||||||
|
"write_ratio": "1"
|
||||||
|
},
|
||||||
|
"description": "test1",
|
||||||
|
"workloadName": "test1"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
searchin: function () {
|
||||||
|
let searchin = Array();
|
||||||
|
if (this.toggle_workspaces === 0) {
|
||||||
|
searchin.push(this.workspace);
|
||||||
|
} else if (this.toggle_workspaces === 1) {
|
||||||
|
console.log("workspaces typeof: '" + typeof (this.workspaces) + "'");
|
||||||
|
this.workspaces.forEach(w => {
|
||||||
|
searchin.push(w.name);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this.toggle_builtins === 0) {
|
||||||
|
searchin.push("builtins");
|
||||||
|
}
|
||||||
|
let joined = searchin.join(",");
|
||||||
|
console.log("joined:'" + joined + "'")
|
||||||
|
return joined;
|
||||||
|
},
|
||||||
|
runin: function () {
|
||||||
|
return "Run Workload";
|
||||||
|
},
|
||||||
|
runtitle: function () {
|
||||||
|
return "Run this workload in workspace [" + this.workspace + "].\n"
|
||||||
|
},
|
||||||
|
workspace: function () {
|
||||||
|
return this.$store.getters["workspaces/getWorkspace"]
|
||||||
|
},
|
||||||
|
workspaces: function () {
|
||||||
|
return this.$store.getters["workspaces/getWorkspaces"]
|
||||||
|
},
|
||||||
|
workloads: function () {
|
||||||
|
return this.$store.getters["workloads/getWorkloads"];
|
||||||
|
},
|
||||||
|
templates: function () {
|
||||||
|
return this.$store.getters["workloads/getTemplates"];
|
||||||
|
}
|
||||||
|
// ,
|
||||||
|
// workloadNames: function () {
|
||||||
|
// for (const [key, value] of Object.entries(this.workloads)) {
|
||||||
|
// console.log("key=[" + key + "] value=[" + value + "]");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
toggle_builtins: function (val) {
|
||||||
|
this.validateAndSearch();
|
||||||
|
},
|
||||||
|
toggle_workspaces: function (val) {
|
||||||
|
this.validateAndSearch();
|
||||||
|
},
|
||||||
|
templates: function (val) {
|
||||||
|
console.log("templates property changed");
|
||||||
|
if (val === undefined) {
|
||||||
|
this.templateparams = undefined;
|
||||||
|
} else {
|
||||||
|
this.templateparams = {};
|
||||||
|
Object.keys(val).forEach(k => {
|
||||||
|
console.log("k:" + k + " = " + val[k])
|
||||||
|
if (!this.templateparams[k]) {
|
||||||
|
this.templateparams[k] = val[k];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.validateAndSearch();
|
||||||
|
this.$store.subscribe((mutation, state) => {
|
||||||
|
if (mutation.type === 'workloads/setWorkloads') {
|
||||||
|
// console.log("detected update to workloads:" + JSON.stringify(this.workloads));
|
||||||
|
this.availableWorkloads = state.workloads.workloads;
|
||||||
|
} else if (mutation.type === 'workspaces/setWorkspace') {
|
||||||
|
// console.log("detected update to workspace:" + JSON.stringify(this.workspace));
|
||||||
|
this.validateAndSearch();
|
||||||
|
}
|
||||||
|
// else if (mutation.type === 'workloads/setTemplates') {
|
||||||
|
// console.log("detected update to templates:" + JSON.stringify(this.workspace));
|
||||||
|
// Object.keys(this.templates).forEach(t => {
|
||||||
|
// console.log("template:" + t)
|
||||||
|
// if (this.templateparams[t]) {
|
||||||
|
// this.templateparams[t] = this.templates[t];
|
||||||
|
// console.log("added '" + this.templates[t])
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
validateAndSearch() {
|
||||||
|
let params = {
|
||||||
|
searchin: this.searchin,
|
||||||
|
reason: "search params changed"
|
||||||
|
}
|
||||||
|
this.$store.dispatch("workloads/fetchWorkloads", params);
|
||||||
|
},
|
||||||
|
loadTemplates() {
|
||||||
|
let params = {
|
||||||
|
workload: this.selected,
|
||||||
|
searchin: this.searchin,
|
||||||
|
reason: "workload selected"
|
||||||
|
}
|
||||||
|
this.$store.dispatch("workloads/fetchTemplates", params);
|
||||||
|
let templates = this.$store.getters["workloads/getTemplates"]
|
||||||
|
|
||||||
|
console.log("templates?" + JSON.stringify(templates, null, 2))
|
||||||
|
// Object.keys(this.templates).forEach(t => {
|
||||||
|
// console.log("t:" + t)
|
||||||
|
// // if (!this.templateparams[t]) {
|
||||||
|
// // this.templateparams[t]=this.templates[t];
|
||||||
|
// // }
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
runWorkload() {
|
||||||
|
console.log("running workload '" + this.selected + "'")
|
||||||
|
// let workload = this.availableWorkloads.find(w => w.workloadName === this.selected);
|
||||||
|
let commands=[];
|
||||||
|
|
||||||
|
commands.push(this.selected);
|
||||||
|
Object.keys(this.templates).forEach(k => {
|
||||||
|
if (this.templateparams && this.templateparams[k]!==this.templates[k]) {
|
||||||
|
commands.push(k+"="+this.templateparams[k])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.keys(this.extraparams).forEach(k => {
|
||||||
|
commands.push(k+"="+this.extraparams[k])
|
||||||
|
})
|
||||||
|
let erq = {
|
||||||
|
scenario_name: this.selected + "_DATESTAMP",
|
||||||
|
workspace: this.workspace,
|
||||||
|
commands
|
||||||
|
}
|
||||||
|
console.log("submitting:" + JSON.stringify(erq));
|
||||||
|
this.$axios.$post("/executor/cli", erq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
/*.container {*/
|
||||||
|
/* margin: 0 auto;*/
|
||||||
|
/* display: flex;*/
|
||||||
|
/* justify-content: center;*/
|
||||||
|
/* align-items: center;*/
|
||||||
|
/* text-align: center;*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
/*.title {*/
|
||||||
|
/* font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,*/
|
||||||
|
/* 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;*/
|
||||||
|
/* display: block;*/
|
||||||
|
/* font-weight: 300;*/
|
||||||
|
/* font-size: 100px;*/
|
||||||
|
/* color: #35495e;*/
|
||||||
|
/* letter-spacing: 1px;*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
/*.subtitle {*/
|
||||||
|
/* font-weight: 300;*/
|
||||||
|
/* font-size: 42px;*/
|
||||||
|
/* color: #526488;*/
|
||||||
|
/* word-spacing: 5px;*/
|
||||||
|
/* padding-bottom: 15px;*/
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
/*.links {*/
|
||||||
|
/* padding-top: 15px;*/
|
||||||
|
/*}*/
|
||||||
|
</style>
|
@ -1,274 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-app>
|
|
||||||
<main-app-bar>NoSQLBench - Workload Executor</main-app-bar>
|
|
||||||
<v-container class="d-flex justify-center">
|
|
||||||
|
|
||||||
<v-main>
|
|
||||||
<v-row fluid class="d-flex">
|
|
||||||
<v-col cols="12" fluid class="d-flex justify-space-between justify-center">
|
|
||||||
|
|
||||||
<v-btn-toggle max="1" v-model="toggle_workspaces" @change="validateAndSearch()">
|
|
||||||
|
|
||||||
<v-btn :disabled="this.toggle_builtins===undefined && this.toggle_workspaces===0">
|
|
||||||
<v-container fluid class="d-flex">
|
|
||||||
<v-icon title="'include ' + workspace">mdi-folder-star</v-icon>
|
|
||||||
<div class="ma-2">workspace '{{ workspace }}'</div>
|
|
||||||
<v-icon v-if="this.toggle_workspaces===0">mdi-check</v-icon>
|
|
||||||
</v-container>
|
|
||||||
</v-btn>
|
|
||||||
|
|
||||||
<v-btn :disabled="this.toggle_builtins===undefined && this.toggle_workspaces===1">
|
|
||||||
<v-container fluid class="d-flex">
|
|
||||||
<v-icon title="search workspaces">mdi-folder-star-multiple</v-icon>
|
|
||||||
<div class="ma-2">all workspaces</div>
|
|
||||||
<v-icon v-if="this.toggle_workspaces===1">mdi-check</v-icon>
|
|
||||||
</v-container>
|
|
||||||
</v-btn>
|
|
||||||
</v-btn-toggle>
|
|
||||||
|
|
||||||
<v-btn-toggle v-model="toggle_builtins" @change="validateAndSearch()">
|
|
||||||
<v-btn :disabled="this.toggle_workspaces===undefined">
|
|
||||||
<v-container fluid class="d-flex">
|
|
||||||
<v-icon title="include built-in workloads">mdi-folder-open</v-icon>
|
|
||||||
<div class="ma-2">bundled</div>
|
|
||||||
<v-icon v-if="this.toggle_builtins===0">mdi-check</v-icon>
|
|
||||||
|
|
||||||
</v-container>
|
|
||||||
</v-btn>
|
|
||||||
</v-btn-toggle>
|
|
||||||
|
|
||||||
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
|
|
||||||
<v-container fluid v-if="workloads!==undefined">
|
|
||||||
|
|
||||||
<v-select
|
|
||||||
:items="availableWorkloads"
|
|
||||||
item-text="description"
|
|
||||||
item-value="workloadName"
|
|
||||||
v-model="workloadName"
|
|
||||||
chips
|
|
||||||
v-on:change="loadTemplates();"
|
|
||||||
label="Workload"
|
|
||||||
></v-select>
|
|
||||||
|
|
||||||
</v-container>
|
|
||||||
|
|
||||||
<v-container fluid>
|
|
||||||
<v-row
|
|
||||||
v-if="templates"
|
|
||||||
>
|
|
||||||
<v-col
|
|
||||||
cols="12"
|
|
||||||
sm="6"
|
|
||||||
md="10"
|
|
||||||
lg="10"
|
|
||||||
>
|
|
||||||
|
|
||||||
<v-card>
|
|
||||||
<v-card-title>
|
|
||||||
{{ this.workloadName }}
|
|
||||||
</v-card-title>
|
|
||||||
<v-col
|
|
||||||
v-for="(item, j) in Object.keys(templates)"
|
|
||||||
:key="item.command"
|
|
||||||
cols="12"
|
|
||||||
sm="6"
|
|
||||||
md="10"
|
|
||||||
lg="10"
|
|
||||||
>
|
|
||||||
<v-text-field
|
|
||||||
v-model="templates[item]"
|
|
||||||
:label="item"
|
|
||||||
>{{ item.name }}
|
|
||||||
</v-text-field>
|
|
||||||
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-btn :title="runtitle" v-if="this.workloadName" v-on:click="runWorkload()">{{ runin }}</v-btn>
|
|
||||||
</v-col>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
|
|
||||||
</v-container>
|
|
||||||
|
|
||||||
</v-main>
|
|
||||||
</v-container>
|
|
||||||
|
|
||||||
<v-footer app>
|
|
||||||
<span>© 2020</span>
|
|
||||||
</v-footer>
|
|
||||||
|
|
||||||
</v-app>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
|
||||||
import AppSelector from "@/components/AppSelector";
|
|
||||||
import MainAppBar from "@/components/MainAppBar";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'app-run',
|
|
||||||
components: {
|
|
||||||
AppSelector,
|
|
||||||
WorkspaceSelector,
|
|
||||||
MainAppBar
|
|
||||||
},
|
|
||||||
data(context) {
|
|
||||||
let data = {
|
|
||||||
availableWorkloads: [],
|
|
||||||
enabled: false,
|
|
||||||
workloadName: null,
|
|
||||||
toggle_builtins: 0,
|
|
||||||
toggle_workspaces: 0,
|
|
||||||
workspace_names: ['current', 'all'],
|
|
||||||
sample: {
|
|
||||||
"workspace": "default",
|
|
||||||
"yamlPath": "test1.yaml",
|
|
||||||
"scenarioNames": [
|
|
||||||
"default",
|
|
||||||
"main"
|
|
||||||
],
|
|
||||||
"templates": {
|
|
||||||
"keyspace": "a",
|
|
||||||
"main-cycles": "10000000",
|
|
||||||
"rampup-cycles": "10000000",
|
|
||||||
"read_cl": "LOCAL_QUORUM",
|
|
||||||
"read_partition_ratio": "1",
|
|
||||||
"read_row_ratio": "1",
|
|
||||||
"write_cl": "LOCAL_QUORUM",
|
|
||||||
"write_ratio": "1"
|
|
||||||
},
|
|
||||||
"description": "test1",
|
|
||||||
"workloadName": "test1"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
searchin: function () {
|
|
||||||
let searchin = Array();
|
|
||||||
if (this.toggle_workspaces === 0) {
|
|
||||||
searchin.push(this.workspace);
|
|
||||||
} else if (this.toggle_workspaces === 1) {
|
|
||||||
console.log("workspaces typeof: '" + typeof (this.workspaces) + "'");
|
|
||||||
this.workspaces.forEach(w => {
|
|
||||||
searchin.push(w.name);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (this.toggle_builtins === 0) {
|
|
||||||
searchin.push("builtins");
|
|
||||||
}
|
|
||||||
let joined = searchin.join(",");
|
|
||||||
console.log("joined:'" + joined + "'")
|
|
||||||
return joined;
|
|
||||||
},
|
|
||||||
runin: function () {
|
|
||||||
return "Run Workload in " + this.$store.getters["workspaces/getWorkspace"];
|
|
||||||
},
|
|
||||||
runtitle: function () {
|
|
||||||
return "Click to run this workload in the '" + this.workspace + "' workspace, or change the workspace in the app bar.\n"
|
|
||||||
},
|
|
||||||
workspace: function () {
|
|
||||||
return this.$store.getters["workspaces/getWorkspace"]
|
|
||||||
},
|
|
||||||
workspaces: function () {
|
|
||||||
return this.$store.getters["workspaces/getWorkspaces"]
|
|
||||||
},
|
|
||||||
workloads: function () {
|
|
||||||
return this.$store.getters["workloads/getWorkloads"];
|
|
||||||
},
|
|
||||||
templates: function () {
|
|
||||||
return this.$store.getters["workloads/getTemplates"];
|
|
||||||
},
|
|
||||||
workloadNames: function () {
|
|
||||||
for (const [key, value] of Object.entries(this.workloads)) {
|
|
||||||
console.log("key=[" + key + "] value=[" + value + "]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
toggle_builtins: function (val) {
|
|
||||||
this.validateAndSearch();
|
|
||||||
},
|
|
||||||
toggle_workspaces: function (val) {
|
|
||||||
this.validateAndSearch();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.validateAndSearch();
|
|
||||||
this.$store.subscribe((mutation, state) => {
|
|
||||||
console.log("mutation type " + mutation.type);
|
|
||||||
if (mutation.type === 'workloads/setWorkloads') {
|
|
||||||
console.log("detected update to workloads:" + JSON.stringify(this.workloads));
|
|
||||||
this.availableWorkloads = state.workloads.workloads;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
validateAndSearch() {
|
|
||||||
|
|
||||||
let params = {
|
|
||||||
searchin: this.searchin,
|
|
||||||
reason: "search params changed"
|
|
||||||
}
|
|
||||||
this.$store.dispatch("workloads/fetchWorkloads", params);
|
|
||||||
},
|
|
||||||
loadTemplates() {
|
|
||||||
let params = {
|
|
||||||
workload: this.workloadName,
|
|
||||||
searchin: this.searchin,
|
|
||||||
reason: "workload selected"
|
|
||||||
}
|
|
||||||
this.$store.dispatch("workloads/fetchTemplates", params);
|
|
||||||
},
|
|
||||||
runWorkload() {
|
|
||||||
console.log("running workload...")
|
|
||||||
let workload = this.availableWorkloads.filter(w => w.workloadName===this.workloadName);
|
|
||||||
let erq = {
|
|
||||||
name: "run_"+workload.workloadName,
|
|
||||||
workspace: this.workspace,
|
|
||||||
commands: [this.workloadName]
|
|
||||||
}
|
|
||||||
console.log("submitting:" + JSON.stringify(erq));
|
|
||||||
this.$axios.$post("services/executor/cli",erq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
/*.container {*/
|
|
||||||
/* margin: 0 auto;*/
|
|
||||||
/* display: flex;*/
|
|
||||||
/* justify-content: center;*/
|
|
||||||
/* align-items: center;*/
|
|
||||||
/* text-align: center;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.title {*/
|
|
||||||
/* font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,*/
|
|
||||||
/* 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;*/
|
|
||||||
/* display: block;*/
|
|
||||||
/* font-weight: 300;*/
|
|
||||||
/* font-size: 100px;*/
|
|
||||||
/* color: #35495e;*/
|
|
||||||
/* letter-spacing: 1px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.subtitle {*/
|
|
||||||
/* font-weight: 300;*/
|
|
||||||
/* font-size: 42px;*/
|
|
||||||
/* color: #526488;*/
|
|
||||||
/* word-spacing: 5px;*/
|
|
||||||
/* padding-bottom: 15px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.links {*/
|
|
||||||
/* padding-top: 15px;*/
|
|
||||||
/*}*/
|
|
||||||
</style>
|
|
226
docsys/src/main/node/docsys/pages/ui/watch.vue
Normal file
226
docsys/src/main/node/docsys/pages/ui/watch.vue
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
<template>
|
||||||
|
<v-app>
|
||||||
|
<main-app-bar>NoSQLBench - Execution Status</main-app-bar>
|
||||||
|
|
||||||
|
<v-main justify-start align-start class="d-inline-block pa-4 ma-10">
|
||||||
|
<div class="row no-gutters">
|
||||||
|
|
||||||
|
<!-- SCENARIO CARD -->
|
||||||
|
|
||||||
|
<v-card min-width="300" max-width="300" max-height="400" raised elevation="3"
|
||||||
|
v-for="(scenario,w) in scenarios" :key="w"
|
||||||
|
class="pa-4 ma-4"
|
||||||
|
:title="JSON.stringify(scenario,null,2)"
|
||||||
|
:color="scenario.state==='Running' ? 'accent' : 'default'">
|
||||||
|
|
||||||
|
<v-row align-content="start" align="start">
|
||||||
|
<v-card-title>{{ scenario.scenario_name }}</v-card-title>
|
||||||
|
<v-card-subtitle>{{ scenario.state }}</v-card-subtitle>
|
||||||
|
<!-- <v-icon>mdi-magnify</v-icon>-->
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<!-- Scenario Controls -->
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-btn
|
||||||
|
v-if="scenario.state==='Running'"
|
||||||
|
@click="stop_scenario(scenario)"
|
||||||
|
:title="'Stop scenario ' + scenario.scenario_name"
|
||||||
|
><v-icon>mdi-stop</v-icon>
|
||||||
|
|
||||||
|
</v-btn>
|
||||||
|
<!-- <v-btn v-if="scenario.state!=='Running'">-->
|
||||||
|
<!-- <v-icon>mdi-play</v-icon>-->
|
||||||
|
<!-- </v-btn>-->
|
||||||
|
<v-btn v-if="scenario.state==='Finished' || scenario.state==='Errored'"
|
||||||
|
:title="'Purge scenario ' + scenario.scenario_name"
|
||||||
|
@click="purge_scenario(scenario)"
|
||||||
|
><v-icon>mdi-delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
<v-btn v-if="scenario.state==='Scheduled'"
|
||||||
|
:title="'cancel scenario ' + scenario.scenario_name"
|
||||||
|
@click="purge_scenario(scenario)"
|
||||||
|
><v-icon>mdi-cancel</v-icon></v-btn>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-divider></v-divider>
|
||||||
|
|
||||||
|
<!-- Activities -->
|
||||||
|
<!-- <v-card-subtitle>activities:</v-card-subtitle>-->
|
||||||
|
<v-row v-for="(progress,p) in scenario.progress" :key="p">
|
||||||
|
<v-card min-width="290" :title="JSON.stringify(progress,null,2)">
|
||||||
|
<v-card-subtitle class="pa-2 ma-2">{{ progress.name }}</v-card-subtitle>
|
||||||
|
<v-progress-linear v-if="progress.completed"
|
||||||
|
:title="(progress.completed*100.0).toFixed(4)"
|
||||||
|
:value="progress_of(progress.completed)"
|
||||||
|
:color="colorof(progress.state)"
|
||||||
|
height="10"
|
||||||
|
></v-progress-linear>
|
||||||
|
<v-card-text v-if="progress.state==='Running'">
|
||||||
|
{{ (progress.eta_millis / 60000).toFixed(2) + " minutes remaining" }}
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-text v-if="scenario.result && scenario.result.error">
|
||||||
|
{{ JSON.stringify(scenario.result.error, null, 2) }}
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-row>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</v-main>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- FOOTER -->
|
||||||
|
|
||||||
|
<v-footer :color="this.paused ? 'secondary' : 'unset'" app>
|
||||||
|
<v-row align="middle">
|
||||||
|
|
||||||
|
<v-progress-circular color="#AAAAAA"
|
||||||
|
width="1"
|
||||||
|
:title="'refresh in '+(this.beats_per_refresh-this.beats_in_refresh) + 's (' + this.beats_per_suffix + ')'"
|
||||||
|
:value="(this.beats_in_refresh/this.beats_per_refresh)*100"
|
||||||
|
@click="do_refresh"
|
||||||
|
>{{ beats_per_refresh - beats_in_refresh }}
|
||||||
|
</v-progress-circular>
|
||||||
|
<v-icon v-if="!this.paused" @click="pause()">mdi-pause</v-icon>
|
||||||
|
<v-icon v-if="this.paused" @click="unpause()">mdi-play</v-icon>
|
||||||
|
<v-icon @click="scale_up">mdi-plus</v-icon>
|
||||||
|
<v-icon @click="scale_down">mdi-minus</v-icon>
|
||||||
|
</v-row>
|
||||||
|
</v-footer>
|
||||||
|
|
||||||
|
</v-app>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
||||||
|
import {mapActions, mapGetters, mapMutations} from "vuex";
|
||||||
|
import AppSelector from "@/components/AppSelector";
|
||||||
|
import MainAppBar from "@/components/MainAppBar";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "workspaces.vue",
|
||||||
|
components: {
|
||||||
|
MainAppBar,
|
||||||
|
AppSelector,
|
||||||
|
WorkspaceSelector
|
||||||
|
},
|
||||||
|
data(context) {
|
||||||
|
let data = {
|
||||||
|
beat: false,
|
||||||
|
beats_per_refresh: 10,
|
||||||
|
beats_in_refresh: 0,
|
||||||
|
beats_per_suffix: '10s',
|
||||||
|
scales: [
|
||||||
|
[1, '1s'], [5, '5s'], [10, '10s'], [20, '20s'], [60, '60s'], [300, '5m'], [600, '10m'], [1800, '15m']
|
||||||
|
],
|
||||||
|
beat_tick: 1000,
|
||||||
|
heart_is_beating: false,
|
||||||
|
paused: false,
|
||||||
|
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scenarios: {
|
||||||
|
get() {
|
||||||
|
return this.$store.getters["scenarios/getScenarios"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
colorof(state) {
|
||||||
|
if (state==='Running') {
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
if (state==='Errored') {
|
||||||
|
return "error"
|
||||||
|
}
|
||||||
|
return "blue";
|
||||||
|
},
|
||||||
|
scale_up() {
|
||||||
|
let idx =Array.from(Array(this.scales.length), (x,i) => i)
|
||||||
|
.find(y => {return this.scales[y][0]===this.beats_per_refresh})
|
||||||
|
idx = Math.min(idx+1,this.scales.length-1);
|
||||||
|
console.log("idx:"+idx)
|
||||||
|
this.beats_per_refresh=this.scales[idx][0];
|
||||||
|
this.beats_per_suffix = this.scales[idx][1];
|
||||||
|
},
|
||||||
|
scale_down() {
|
||||||
|
let idx =Array.from(Array(this.scales.length), (x,i) => i)
|
||||||
|
.find(y => {return this.scales[y][0]===this.beats_per_refresh})
|
||||||
|
idx = Math.max(idx-1,0);
|
||||||
|
console.log("idx:"+idx)
|
||||||
|
this.beats_per_refresh=this.scales[idx][0];
|
||||||
|
this.beats_per_suffix = this.scales[idx][1];
|
||||||
|
},
|
||||||
|
stop_scenario(scenario) {
|
||||||
|
console.log("stopping scenario: " + scenario.scenario_name);
|
||||||
|
this.$store.dispatch("scenarios/stopScenario", scenario.scenario_name)
|
||||||
|
this.do_refresh();
|
||||||
|
},
|
||||||
|
purge_scenario(scenario) {
|
||||||
|
console.log("purging scenario: " + scenario.scenario_name);
|
||||||
|
this.$store.dispatch("scenarios/deleteScenario", scenario.scenario_name);
|
||||||
|
this.do_refresh();
|
||||||
|
},
|
||||||
|
pause() {
|
||||||
|
this.paused = true;
|
||||||
|
},
|
||||||
|
unpause() {
|
||||||
|
this.paused = false;
|
||||||
|
this.heartbeat();
|
||||||
|
},
|
||||||
|
heartbeat() {
|
||||||
|
this.heart_is_beating = false;
|
||||||
|
if (this.paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let seconds = new Date().getSeconds();
|
||||||
|
// console.log("seconds:" + seconds);
|
||||||
|
this.beat = (seconds % 2) === 0;
|
||||||
|
this.beats_in_refresh++;
|
||||||
|
if (this.beats_in_refresh >= this.beats_per_refresh) {
|
||||||
|
this.do_refresh();
|
||||||
|
}
|
||||||
|
if (!this.heart_is_beating) {
|
||||||
|
this.heart_is_beating = true;
|
||||||
|
setTimeout(this.heartbeat, this.beat_tick);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
do_refresh() {
|
||||||
|
this.beats_in_refresh = 0;
|
||||||
|
this.$store.dispatch("scenarios/loadScenarios", "timer refresh")
|
||||||
|
},
|
||||||
|
progress_of(completion) {
|
||||||
|
if (isNaN(completion)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
let progress = (completion * 100.0).toFixed(2);
|
||||||
|
return progress;
|
||||||
|
},
|
||||||
|
is_running(scenario) {
|
||||||
|
return scenario.progress.find(x => {
|
||||||
|
return x.state === "Running"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
abbrev(name) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
console.log("created component...");
|
||||||
|
this.$store.dispatch("scenarios/loadScenarios", "watch panel load");
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
setTimeout(this.heartbeat, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
@ -1,146 +0,0 @@
|
|||||||
<template>
|
|
||||||
<v-app>
|
|
||||||
<main-app-bar>NoSQLBench - Execution Status</main-app-bar>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
{
|
|
||||||
"summary": {
|
|
||||||
"total_bytes": 24,
|
|
||||||
"total_files": 1,
|
|
||||||
"last_change": 1597293397043,
|
|
||||||
"last_file_changed": "README.md"
|
|
||||||
},
|
|
||||||
"name": "default",
|
|
||||||
"modified": 1597293397043,
|
|
||||||
"changed": "README.md (1H17M27S ago)"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
-->
|
|
||||||
|
|
||||||
<v-main justify-start align-start class="d-inline-block pa-4 ma-10">
|
|
||||||
<div class="row no-gutters">
|
|
||||||
<v-card min-width="300" max-width="300" max-height="400" raised elevation="5"
|
|
||||||
v-for="(invocation,w) in invocations" :key="w"
|
|
||||||
class="pa-4 ma-4" :loading="is_loading(invocation)">
|
|
||||||
<v-row :title="JSON.stringify(invocation)">
|
|
||||||
<v-card-title title="running scenario name">{{ invocation.scenario_name }}</v-card-title>
|
|
||||||
<!-- <v-icon v-if="workspace === cardspace.name">mdi-check-bold</v-icon>-->
|
|
||||||
</v-row>
|
|
||||||
<v-card-subtitle title="title">sdf</v-card-subtitle>
|
|
||||||
<v-card-subtitle title="started at">{{invocation.started_at}}</v-card-subtitle>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <v-card-subtitle title="last change">{{ abbrev(invocation.summary.last_changed_filename) }}</v-card-subtitle>-->
|
|
||||||
<!-- <v-divider></v-divider>-->
|
|
||||||
<!-- <v-list align-start>-->
|
|
||||||
<!-- <v-simple-table>-->
|
|
||||||
<!-- <tbody>-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <td>Bytes</td>-->
|
|
||||||
<!-- <td>{{ invocation.summary.total_bytes }}</td>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- <tr>-->
|
|
||||||
<!-- <td>Files</td>-->
|
|
||||||
<!-- <td>{{ invocation.summary.total_files }}</td>-->
|
|
||||||
<!-- </tr>-->
|
|
||||||
<!-- </tbody>-->
|
|
||||||
<!-- </v-simple-table>-->
|
|
||||||
<!-- <v-divider></v-divider>-->
|
|
||||||
|
|
||||||
<!-- <v-list-item>-->
|
|
||||||
<!-- <v-btn title="view details of workspace">-->
|
|
||||||
<!-- <v-icon>mdi-magnify</v-icon>-->
|
|
||||||
<!-- </v-btn>-->
|
|
||||||
|
|
||||||
<!-- <!– <v-btn title="use this workspace">–>-->
|
|
||||||
<!-- <!– <v-icon>mdi-play</v-icon>–>-->
|
|
||||||
<!-- <!– </v-btn>–>-->
|
|
||||||
|
|
||||||
<!-- <v-spacer></v-spacer>-->
|
|
||||||
|
|
||||||
<!-- <v-btn title="download zipped workspace">-->
|
|
||||||
<!-- <v-icon>mdi-folder-download</v-icon>-->
|
|
||||||
<!-- </v-btn>-->
|
|
||||||
|
|
||||||
<!-- <v-spacer></v-spacer>-->
|
|
||||||
|
|
||||||
<!-- <v-btn title="purge workspace">-->
|
|
||||||
<!-- <v-icon @click="purgeWorkspace(cardspace.name)">mdi-trash-can</v-icon>-->
|
|
||||||
<!-- </v-btn>-->
|
|
||||||
|
|
||||||
<!-- </v-list-item>-->
|
|
||||||
<!-- </v-list>-->
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
</v-main>
|
|
||||||
|
|
||||||
</v-app>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
|
||||||
import {mapActions, mapGetters, mapMutations} from "vuex";
|
|
||||||
import AppSelector from "@/components/AppSelector";
|
|
||||||
import MainAppBar from "@/components/MainAppBar";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "workspaces.vue",
|
|
||||||
components: {
|
|
||||||
MainAppBar,
|
|
||||||
AppSelector,
|
|
||||||
WorkspaceSelector
|
|
||||||
},
|
|
||||||
data(context) {
|
|
||||||
let data = {
|
|
||||||
// invocations: [
|
|
||||||
// {
|
|
||||||
// "scenario_name": "mytestscenario",
|
|
||||||
// "progress": [
|
|
||||||
// {
|
|
||||||
// "name": "/tmp/nosqlbench/mytestscenario3888869514662003808file1.yaml",
|
|
||||||
// "state": "Running",
|
|
||||||
// "details": "min=0 cycle=1692 max=10000000",
|
|
||||||
// "completed": 1.692E-4
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
// "started_at": 1597749369800,
|
|
||||||
// "ended_at": -1,
|
|
||||||
// "activity_states": [
|
|
||||||
// {
|
|
||||||
// "completion": "1.692E-4",
|
|
||||||
// "name": "/tmp/nosqlbench/mytestscenario3888869514662003808file1.yaml",
|
|
||||||
// "state": "Running"
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
};
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
invocations: {
|
|
||||||
get() {
|
|
||||||
return this.$store.getters["invocations/getInvocations"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
is_loading(invocation) {
|
|
||||||
let found = invocation.progress.find(p => {p.state==='Running'});
|
|
||||||
return !!found;
|
|
||||||
},
|
|
||||||
abbrev(name) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
console.log("created component...");
|
|
||||||
this.$store.dispatch("invocations/loadInvocations", "watch panel load");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
</style>
|
|
@ -72,7 +72,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import WorkspaceSelector from "~/components/WorkspaceSelector";
|
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
||||||
import {mapActions, mapGetters, mapMutations} from "vuex";
|
import {mapActions, mapGetters, mapMutations} from "vuex";
|
||||||
import AppSelector from "@/components/AppSelector";
|
import AppSelector from "@/components/AppSelector";
|
||||||
import MainAppBar from "@/components/MainAppBar";
|
import MainAppBar from "@/components/MainAppBar";
|
86
docsys/src/main/node/docsys/pages/ui/workspaces/detail.vue
Normal file
86
docsys/src/main/node/docsys/pages/ui/workspaces/detail.vue
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<v-app>
|
||||||
|
<main-app-bar></main-app-bar>
|
||||||
|
|
||||||
|
<!-- <workspace-selector @changed="seenChange(workspace)"></workspace-selector>-->
|
||||||
|
|
||||||
|
<!-- <v-btn title="start a new workspace" @click="startNewWorkspace()">-->
|
||||||
|
<!-- <v-icon>mdi-folder-plus-outline</v-icon>-->
|
||||||
|
<!-- </v-btn>-->
|
||||||
|
|
||||||
|
<!-- <v-btn icon title="upload a workspace zip file">-->
|
||||||
|
<!-- <v-icon>mdi-folder-upload</v-icon>-->
|
||||||
|
<!-- </v-btn>-->
|
||||||
|
<!-- <v-btn icon title="download workspaces.zip">-->
|
||||||
|
<!-- <v-icon>mdi-briefcase-download</v-icon>-->
|
||||||
|
<!-- </v-btn>-->
|
||||||
|
<!-- <v-btn icon title="upload workspaces.zip">-->
|
||||||
|
<!-- <v-icon>mdi-briefcase-upload</v-icon>-->
|
||||||
|
<!-- </v-btn>-->
|
||||||
|
|
||||||
|
<v-content justify-start align-start class="d-inline-block pa-4 ma-10">
|
||||||
|
<div class="row no-gutters">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</v-content>
|
||||||
|
|
||||||
|
</v-app>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import WorkspaceSelector from "~/components/WorkspaceSelector";
|
||||||
|
import {mapActions, mapGetters, mapMutations} from "vuex";
|
||||||
|
import AppSelector from "@/components/AppSelector";
|
||||||
|
import MainAppBar from "@/components/MainAppBar";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "workspaces.vue",
|
||||||
|
components: {
|
||||||
|
MainAppBar,
|
||||||
|
AppSelector,
|
||||||
|
WorkspaceSelector
|
||||||
|
},
|
||||||
|
data(context) {
|
||||||
|
let data = {};
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
workspace: {
|
||||||
|
get() {
|
||||||
|
return this.$store.getters["workspaces/getWorkspace"]
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$store.dispatch("workspaces/setWorkspace", val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
workspaces: {
|
||||||
|
get() {
|
||||||
|
return this.$store.getters["workspaces/getWorkspaces"]
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$store.dispatch("workspaces/setWorkspaces", val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
abbrev(name) {
|
||||||
|
return name;
|
||||||
|
},
|
||||||
|
purgeWorkspace: function (ws) {
|
||||||
|
console.log("purging " + ws);
|
||||||
|
this.$store.dispatch('workspaces/purgeWorkspace', ws);
|
||||||
|
// this.$store.dispatch("workspaces/setWorkspace")
|
||||||
|
this.$forceUpdate();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
console.log("created component...");
|
||||||
|
this.$store.dispatch('workspaces/initWorkspaces', "workspace panel load");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
@ -62,7 +62,7 @@ export const getters = {
|
|||||||
throw "unable to load active markdown for undefined category";
|
throw "unable to load active markdown for undefined category";
|
||||||
}
|
}
|
||||||
if (state.active_topic===null) {
|
if (state.active_topic===null) {
|
||||||
throw "uanble to load active markdown for undefined topic";
|
throw "unable to load active markdown for undefined topic";
|
||||||
}
|
}
|
||||||
return state.active_topic.content;
|
return state.active_topic.content;
|
||||||
}
|
}
|
||||||
@ -78,13 +78,6 @@ export const mutations = {
|
|||||||
setCategories(state, categories) {
|
setCategories(state, categories) {
|
||||||
state.categories = categories;
|
state.categories = categories;
|
||||||
},
|
},
|
||||||
// initializeStore(state) {
|
|
||||||
// if(localStorage.getItem('store')) {
|
|
||||||
// this.replaceState(
|
|
||||||
// Object.assign(state,JSON.parse(localStorage.getItem('store')))
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
toggleDrawerState(state, newDrawerState) {
|
toggleDrawerState(state, newDrawerState) {
|
||||||
if (state.isMenuLocked) {
|
if (state.isMenuLocked) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
// https://www.mikestreety.co.uk/blog/vue-js-using-localstorage-with-the-vuex-store
|
|
||||||
import {mapGetters} from "vuex";
|
|
||||||
|
|
||||||
export const state = () => ({
|
|
||||||
invocations: []
|
|
||||||
});
|
|
||||||
|
|
||||||
export const getters = {
|
|
||||||
getInvocations: (state, getters) => {
|
|
||||||
return state.invocations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const mutations = {
|
|
||||||
setInvocations(state, invocations) {
|
|
||||||
state.invocations = invocations;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const actions = {
|
|
||||||
async loadInvocations({commit, state, dispatch}, reason) {
|
|
||||||
console.log("initializing scenarios because '" + reason + "'")
|
|
||||||
this.$axios.$get("/executor/scenarios/")
|
|
||||||
.then(res => {
|
|
||||||
console.log("axios/vuex invocations async get:" + JSON.stringify(res));
|
|
||||||
console.log("committing setInvocations:" + JSON.stringify(res));
|
|
||||||
commit('setInvocations', res)
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
console.error("axios/nuxt invocations async error:", e);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
49
docsys/src/main/node/docsys/store/scenarios.js
Normal file
49
docsys/src/main/node/docsys/store/scenarios.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// https://www.mikestreety.co.uk/blog/vue-js-using-localstorage-with-the-vuex-store
|
||||||
|
import {mapGetters} from "vuex";
|
||||||
|
|
||||||
|
export const state = () => ({
|
||||||
|
scenarios: []
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getters = {
|
||||||
|
getScenarios: (state, getters) => {
|
||||||
|
return state.scenarios;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mutations = {
|
||||||
|
setScenarios(state, scenarios) {
|
||||||
|
state.scenarios = scenarios;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const actions = {
|
||||||
|
async loadScenarios({commit, state, dispatch}, reason) {
|
||||||
|
console.log("loading scenarios because '" + reason + "'")
|
||||||
|
await this.$axios.$get("/executor/scenarios/")
|
||||||
|
.then(res => {
|
||||||
|
// console.log("axios/vuex scenarios async get:" + JSON.stringify(res));
|
||||||
|
// console.log("committing setScenarios:" + JSON.stringify(res));
|
||||||
|
commit('setScenarios', res)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error("axios/nuxt scenarios async error:", e);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async stopScenario({commit, state, dispatch}, scenario_name) {
|
||||||
|
await this.$axios.$post("/executor/stop/" + scenario_name)
|
||||||
|
.then()
|
||||||
|
.catch((e) => {
|
||||||
|
console.error("axios/nuxt scenario stop error:", e);
|
||||||
|
})
|
||||||
|
await dispatch("loadScenarios")
|
||||||
|
},
|
||||||
|
async deleteScenario({commit, state, dispatch}, scenario_name) {
|
||||||
|
await this.$axios.$delete("/executor/scenario/" + scenario_name)
|
||||||
|
.then()
|
||||||
|
.catch((e) => {
|
||||||
|
console.error("axios/nuxt scenario stop error:", e);
|
||||||
|
})
|
||||||
|
await dispatch("loadScenarios")
|
||||||
|
}
|
||||||
|
};
|
@ -33,36 +33,36 @@ export const mutations = {
|
|||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
async setWorkloads({commit, state, dispatch}, val) {
|
async setWorkloads({commit, state, dispatch}, val) {
|
||||||
console.log("committing setWorkloads:" + JSON.stringify(val));
|
// console.log("committing setWorkloads:" + JSON.stringify(val));
|
||||||
commit('setWorkloads', val);
|
commit('setWorkloads', val);
|
||||||
},
|
},
|
||||||
async setTemplates({commit, state, dispatch}, val) {
|
async setTemplates({commit, state, dispatch}, val) {
|
||||||
console.log("commiting setTemplates:" + JSON.stringify(val));
|
// console.log("commiting setTemplates:" + JSON.stringify(val));
|
||||||
commit("setTemplates", val);
|
commit("setTemplates", val);
|
||||||
},
|
},
|
||||||
async setSearchin({commit, state, dispatch}, val) {
|
async setSearchin({commit, state, dispatch}, val) {
|
||||||
console.log("committing setsearchin:" + JSON.stringify(val));
|
// console.log("committing setsearchin:" + JSON.stringify(val));
|
||||||
commit('setSearchin', val);
|
commit('setSearchin', val);
|
||||||
},
|
},
|
||||||
fetchWorkloads({commit, state, dispatch}, params) {
|
async fetchWorkloads({commit, state, dispatch}, params) {
|
||||||
let reason = params.reason;
|
let reason = params.reason;
|
||||||
let searchin = params.searchin;
|
let searchin = params.searchin;
|
||||||
if (reason === undefined || searchin === undefined) {
|
if (reason === undefined || searchin === undefined) {
|
||||||
throw "Unable to fetch workloads without a reason or searchin: " + JSON.stringify(params);
|
throw "Unable to fetch workloads without a reason or searchin: " + JSON.stringify(params);
|
||||||
}
|
}
|
||||||
console.log("fetching workloads because '" + reason + "'")
|
// console.log("fetching workloads because '" + reason + "'")
|
||||||
|
|
||||||
commit("setTemplates", undefined);
|
commit("setTemplates", undefined);
|
||||||
this.$axios.$get("/workloads/?searchin=" + searchin)
|
this.$axios.$get("/workloads/?searchin=" + searchin)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
console.log("axios/vuex workloads async get:" + JSON.stringify(res));
|
// console.log("axios/vuex workloads async get:" + JSON.stringify(res));
|
||||||
commit("setWorkloads", res);
|
commit("setWorkloads", res);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("axios/nuxt workloads async error:", e);
|
console.error("axios/nuxt workloads async error:", e);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async fetchTemplates({commit, state, dispatch}, params) {
|
fetchTemplates({commit, state, dispatch}, params) {
|
||||||
let reason = params.reason;
|
let reason = params.reason;
|
||||||
let workload = params.workload;
|
let workload = params.workload;
|
||||||
let searchin = params.searchin;
|
let searchin = params.searchin;
|
||||||
@ -71,13 +71,15 @@ export const actions = {
|
|||||||
}
|
}
|
||||||
console.log("fetching templates for '" + workload + "' because '" + reason + "'")
|
console.log("fetching templates for '" + workload + "' because '" + reason + "'")
|
||||||
|
|
||||||
this.$axios.$get("/workloads/parameters?workloadName=" + workload + "&" + searchin)
|
this.$axios.$get("/workloads/parameters?workloadName=" + workload + "&" + "searchin=" + searchin)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
console.log("axios/vuex templates async get:" + JSON.stringify(res));
|
// console.log("axios/vuex templates async get:" + JSON.stringify(res));
|
||||||
dispatch("setTemplates", res);
|
dispatch("setTemplates", res);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.error("axios/nuxt templates async error:", e);
|
console.error("axios/nuxt templates async error:", e);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,8 @@ import {mapGetters} from "vuex";
|
|||||||
|
|
||||||
export const state = () => ({
|
export const state = () => ({
|
||||||
workspace: 'default',
|
workspace: 'default',
|
||||||
workspaces: []
|
workspaces: [],
|
||||||
|
fileview: []
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getters = {
|
export const getters = {
|
||||||
@ -12,6 +13,9 @@ export const getters = {
|
|||||||
},
|
},
|
||||||
getWorkspaces: (state, getters) => {
|
getWorkspaces: (state, getters) => {
|
||||||
return state.workspaces;
|
return state.workspaces;
|
||||||
|
},
|
||||||
|
getFileview: (state, getters) => {
|
||||||
|
return state.fileview;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...mapGetters(['workspace','workspaces'])
|
// ...mapGetters(['workspace','workspaces'])
|
||||||
@ -23,24 +27,27 @@ export const mutations = {
|
|||||||
},
|
},
|
||||||
setWorkspaces(state, workspaces) {
|
setWorkspaces(state, workspaces) {
|
||||||
state.workspaces = workspaces;
|
state.workspaces = workspaces;
|
||||||
|
},
|
||||||
|
setFileview(state, fileview) {
|
||||||
|
state.fileview = fileview;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
async setWorkspace({commit, state, dispatch}, val) {
|
async setWorkspace({commit, state, dispatch}, val) {
|
||||||
console.log("committing setWorkspace:" + JSON.stringify(val));
|
// console.log("committing setWorkspace:" + JSON.stringify(val));
|
||||||
commit('setWorkspace', val);
|
commit('setWorkspace', val);
|
||||||
},
|
},
|
||||||
async setWorkspaces({commit, state, dispatch}, val) {
|
async setWorkspaces({commit, state, dispatch}, val) {
|
||||||
console.log("committing setWorkspaces:" + JSON.stringify(val));
|
// console.log("committing setWorkspaces:" + JSON.stringify(val));
|
||||||
commit('setWorkspaces', val);
|
commit('setWorkspaces', val);
|
||||||
},
|
},
|
||||||
async initWorkspaces({commit, state, dispatch}, reason) {
|
async initWorkspaces({commit, state, dispatch}, reason) {
|
||||||
console.log("initializing workspaces because '" + reason + "'")
|
// console.log("initializing workspaces because '" + reason + "'")
|
||||||
this.$axios.$get("/workspaces/")
|
this.$axios.$get("/workspaces/")
|
||||||
.then(res => {
|
.then(res => {
|
||||||
console.log("axios/vuex workspaces async get:" + JSON.stringify(res));
|
// console.log("axios/vuex workspaces async get:" + JSON.stringify(res));
|
||||||
console.log("committing setWorkspaces:" + JSON.stringify(res));
|
// console.log("committing setWorkspaces:" + JSON.stringify(res));
|
||||||
commit('setWorkspaces', res)
|
commit('setWorkspaces', res)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@ -66,7 +73,7 @@ export const actions = {
|
|||||||
async activateWorkspace({commit, state, dispatch}, workspace) {
|
async activateWorkspace({commit, state, dispatch}, workspace) {
|
||||||
const fresh_workspace = await this.$axios.$get("/workspaces/" + workspace)
|
const fresh_workspace = await this.$axios.$get("/workspaces/" + workspace)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
console.log("axios/vuex workspace async get:" + JSON.stringify(res))
|
// console.log("axios/vuex workspace async get:" + JSON.stringify(res))
|
||||||
return res;
|
return res;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
@ -25,6 +25,8 @@ import io.nosqlbench.engine.api.activityapi.ratelimits.RateLimiter;
|
|||||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
||||||
import io.nosqlbench.engine.api.activityimpl.SimpleActivity;
|
import io.nosqlbench.engine.api.activityimpl.SimpleActivity;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.input.StateCapable;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@ -34,15 +36,17 @@ import java.util.function.Supplier;
|
|||||||
* Provides the components needed to build and run an activity a runtime.
|
* Provides the components needed to build and run an activity a runtime.
|
||||||
* The easiest way to build a useful Activity is to extend {@link SimpleActivity}.
|
* The easiest way to build a useful Activity is to extend {@link SimpleActivity}.
|
||||||
*/
|
*/
|
||||||
public interface Activity extends Comparable<Activity>, ActivityDefObserver {
|
public interface Activity extends Comparable<Activity>, ActivityDefObserver, ProgressCapable, StateCapable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide the activity with the controls needed to stop itself.
|
* Provide the activity with the controls needed to stop itself.
|
||||||
|
*
|
||||||
* @param activityController The dedicated control interface for this activity
|
* @param activityController The dedicated control interface for this activity
|
||||||
*/
|
*/
|
||||||
void setActivityController(ActivityController activityController);
|
void setActivityController(ActivityController activityController);
|
||||||
|
|
||||||
ActivityController getActivityController();
|
ActivityController getActivityController();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register an object which should be closed after this activity is shutdown.
|
* Register an object which should be closed after this activity is shutdown.
|
||||||
*
|
*
|
||||||
@ -89,8 +93,11 @@ public interface Activity extends Comparable<Activity>, ActivityDefObserver {
|
|||||||
void setOutputDispenserDelegate(OutputDispenser outputDispenser);
|
void setOutputDispenserDelegate(OutputDispenser outputDispenser);
|
||||||
|
|
||||||
RunState getRunState();
|
RunState getRunState();
|
||||||
|
|
||||||
void setRunState(RunState runState);
|
void setRunState(RunState runState);
|
||||||
|
|
||||||
|
long getStartedAtMillis();
|
||||||
|
|
||||||
default void shutdownActivity() {
|
default void shutdownActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,47 @@
|
|||||||
package io.nosqlbench.engine.api.activityapi.core;
|
package io.nosqlbench.engine.api.activityapi.core;
|
||||||
|
|
||||||
public interface ProgressMeter {
|
public interface ProgressMeter {
|
||||||
double getProgress();
|
|
||||||
String getProgressName();
|
String getProgressName();
|
||||||
RunState getProgressState();
|
|
||||||
String getProgressDetails();
|
// RunState getProgressState();
|
||||||
|
long getStartedAtMillis();
|
||||||
|
|
||||||
|
long getProgressMin();
|
||||||
|
|
||||||
|
long getProgressCurrent();
|
||||||
|
|
||||||
|
long getProgressMax();
|
||||||
|
|
||||||
|
long getRecyclesCurrent();
|
||||||
|
|
||||||
|
long getRecyclesMax();
|
||||||
|
|
||||||
|
default String getProgressSummary() {
|
||||||
|
return "min=" + getProgressMin() + " cycle=" + getProgressCurrent() + " max=" + getProgressMax() +
|
||||||
|
(getRecyclesMax() > 0L ? " recycles=" + getRecyclesCurrent() + "/" + getRecyclesMax() : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
default double getProgressRatio() {
|
||||||
|
return
|
||||||
|
((double) (getProgressCurrent() - getProgressMin()))
|
||||||
|
/
|
||||||
|
((double) (getProgressMax() - getProgressMin()));
|
||||||
|
}
|
||||||
|
|
||||||
|
default double getProgressTotal() {
|
||||||
|
return (getProgressMax() - getProgressMin());
|
||||||
|
}
|
||||||
|
|
||||||
|
default double getProgressETAMillis() {
|
||||||
|
long then = getStartedAtMillis();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
double elapsed = now - then;
|
||||||
|
|
||||||
|
double completed = getProgressCurrent() - getProgressMin();
|
||||||
|
double rate = completed / elapsed;
|
||||||
|
|
||||||
|
double remaining = getProgressMax() - getProgressCurrent();
|
||||||
|
return remaining / rate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package io.nosqlbench.engine.api.activityimpl;
|
||||||
|
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.ProgressMeter;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.RunState;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.input.StateCapable;
|
||||||
|
|
||||||
|
public class ProgressAndStateMeter implements ProgressMeter, StateCapable {
|
||||||
|
private final ProgressMeter meter;
|
||||||
|
private final StateCapable statesrc;
|
||||||
|
|
||||||
|
public ProgressAndStateMeter(ProgressMeter meter, StateCapable statesrc) {
|
||||||
|
this.meter = meter;
|
||||||
|
this.statesrc = statesrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProgressName() {
|
||||||
|
return meter.getProgressName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getStartedAtMillis() {
|
||||||
|
return meter.getStartedAtMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getProgressMin() {
|
||||||
|
return meter.getProgressMin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getProgressCurrent() {
|
||||||
|
return meter.getProgressCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getProgressMax() {
|
||||||
|
return meter.getProgressMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRecyclesCurrent() {
|
||||||
|
return meter.getRecyclesCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRecyclesMax() {
|
||||||
|
return meter.getRecyclesMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RunState getRunState() {
|
||||||
|
return statesrc.getRunState();
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package io.nosqlbench.engine.api.activityimpl;
|
|||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
import io.nosqlbench.engine.api.activityapi.core.*;
|
import io.nosqlbench.engine.api.activityapi.core.*;
|
||||||
import io.nosqlbench.engine.api.activityapi.cyclelog.filters.IntPredicateDispenser;
|
import io.nosqlbench.engine.api.activityapi.cyclelog.filters.IntPredicateDispenser;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.input.Input;
|
||||||
import io.nosqlbench.engine.api.activityapi.input.InputDispenser;
|
import io.nosqlbench.engine.api.activityapi.input.InputDispenser;
|
||||||
import io.nosqlbench.engine.api.activityapi.output.OutputDispenser;
|
import io.nosqlbench.engine.api.activityapi.output.OutputDispenser;
|
||||||
import io.nosqlbench.engine.api.activityapi.planning.OpSequence;
|
import io.nosqlbench.engine.api.activityapi.planning.OpSequence;
|
||||||
@ -14,6 +15,7 @@ import io.nosqlbench.engine.api.activityapi.ratelimits.RateSpec;
|
|||||||
import io.nosqlbench.engine.api.activityconfig.StatementsLoader;
|
import io.nosqlbench.engine.api.activityconfig.StatementsLoader;
|
||||||
import io.nosqlbench.engine.api.activityconfig.yaml.OpTemplate;
|
import io.nosqlbench.engine.api.activityconfig.yaml.OpTemplate;
|
||||||
import io.nosqlbench.engine.api.activityconfig.yaml.StmtsDocList;
|
import io.nosqlbench.engine.api.activityconfig.yaml.StmtsDocList;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable;
|
||||||
import io.nosqlbench.engine.api.metrics.ActivityMetrics;
|
import io.nosqlbench.engine.api.metrics.ActivityMetrics;
|
||||||
import io.nosqlbench.engine.api.templating.CommandTemplate;
|
import io.nosqlbench.engine.api.templating.CommandTemplate;
|
||||||
import io.nosqlbench.engine.api.templating.StrInterpolator;
|
import io.nosqlbench.engine.api.templating.StrInterpolator;
|
||||||
@ -32,11 +34,11 @@ import java.util.function.Supplier;
|
|||||||
/**
|
/**
|
||||||
* A default implementation of an Activity, suitable for building upon.
|
* A default implementation of an Activity, suitable for building upon.
|
||||||
*/
|
*/
|
||||||
public class SimpleActivity implements Activity {
|
public class SimpleActivity implements Activity, ProgressCapable {
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SimpleActivity.class);
|
private final static Logger logger = LoggerFactory.getLogger(SimpleActivity.class);
|
||||||
|
|
||||||
protected ActivityDef activityDef;
|
protected ActivityDef activityDef;
|
||||||
private List<AutoCloseable> closeables = new ArrayList<>();
|
private final List<AutoCloseable> closeables = new ArrayList<>();
|
||||||
private MotorDispenser motorDispenser;
|
private MotorDispenser motorDispenser;
|
||||||
private InputDispenser inputDispenser;
|
private InputDispenser inputDispenser;
|
||||||
private ActionDispenser actionDispenser;
|
private ActionDispenser actionDispenser;
|
||||||
@ -49,6 +51,7 @@ public class SimpleActivity implements Activity {
|
|||||||
private ActivityController activityController;
|
private ActivityController activityController;
|
||||||
private ActivityInstrumentation activityInstrumentation;
|
private ActivityInstrumentation activityInstrumentation;
|
||||||
private PrintWriter console;
|
private PrintWriter console;
|
||||||
|
private long startedAtMillis;
|
||||||
|
|
||||||
public SimpleActivity(ActivityDef activityDef) {
|
public SimpleActivity(ActivityDef activityDef) {
|
||||||
this.activityDef = activityDef;
|
this.activityDef = activityDef;
|
||||||
@ -70,6 +73,14 @@ public class SimpleActivity implements Activity {
|
|||||||
|
|
||||||
public synchronized void setRunState(RunState runState) {
|
public synchronized void setRunState(RunState runState) {
|
||||||
this.runState = runState;
|
this.runState = runState;
|
||||||
|
if (runState == RunState.Running) {
|
||||||
|
this.startedAtMillis = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getStartedAtMillis() {
|
||||||
|
return startedAtMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -207,6 +218,7 @@ public class SimpleActivity implements Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Timer getResultTimer() {
|
public Timer getResultTimer() {
|
||||||
return ActivityMetrics.timer(getActivityDef(), "result");
|
return ActivityMetrics.timer(getActivityDef(), "result");
|
||||||
@ -399,4 +411,16 @@ public class SimpleActivity implements Activity {
|
|||||||
return planner.resolve();
|
return planner.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProgressMeter getProgressMeter() {
|
||||||
|
Input input = getInputDispenserDelegate().getInput(0);
|
||||||
|
if (input instanceof ProgressCapable) {
|
||||||
|
ProgressMeter meter = ((ProgressCapable) input).getProgressMeter();
|
||||||
|
return new ProgressAndStateMeter(meter, this);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Progress meter must be implemented here.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package io.nosqlbench.engine.api.activityimpl.input;
|
package io.nosqlbench.engine.api.activityimpl.input;
|
||||||
|
|
||||||
import io.nosqlbench.engine.api.activityapi.core.ActivityDefObserver;
|
import io.nosqlbench.engine.api.activityapi.core.ActivityDefObserver;
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.ProgressMeter;
|
||||||
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.CycleSegment;
|
import io.nosqlbench.engine.api.activityapi.cyclelog.buffers.results.CycleSegment;
|
||||||
import io.nosqlbench.engine.api.activityapi.input.Input;
|
import io.nosqlbench.engine.api.activityapi.input.Input;
|
||||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
@ -50,8 +51,9 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
|||||||
|
|
||||||
private final AtomicLong recycleValue = new AtomicLong(0L);
|
private final AtomicLong recycleValue = new AtomicLong(0L);
|
||||||
private final AtomicLong recycleMax = new AtomicLong(0L);
|
private final AtomicLong recycleMax = new AtomicLong(0L);
|
||||||
|
private final long startedAt = System.currentTimeMillis();
|
||||||
|
|
||||||
private ActivityDef activityDef;
|
private final ActivityDef activityDef;
|
||||||
|
|
||||||
public AtomicInput(ActivityDef activityDef) {
|
public AtomicInput(ActivityDef activityDef) {
|
||||||
this.activityDef = activityDef;
|
this.activityDef = activityDef;
|
||||||
@ -64,15 +66,15 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
|||||||
long current = this.cycleValue.get();
|
long current = this.cycleValue.get();
|
||||||
long next = current + stride;
|
long next = current + stride;
|
||||||
if (next > max.get()) {
|
if (next > max.get()) {
|
||||||
if (recycleValue.get()>=recycleMax.get()) {
|
if (recycleValue.get() >= recycleMax.get()) {
|
||||||
logger.trace("Exhausted input for " + activityDef.getAlias() + " at " + current + ", recycle " +
|
logger.trace("Exhausted input for " + activityDef.getAlias() + " at " + current + ", recycle " +
|
||||||
"count " + recycleValue.get());
|
"count " + recycleValue.get());
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
if (cycleValue.compareAndSet(current,min.get()+stride)) {
|
if (cycleValue.compareAndSet(current, min.get() + stride)) {
|
||||||
recycleValue.getAndIncrement();
|
recycleValue.getAndIncrement();
|
||||||
logger.trace("recycling input for " + activityDef.getAlias() + " recycle:" + recycleValue.get());
|
logger.trace("recycling input for " + activityDef.getAlias() + " recycle:" + recycleValue.get());
|
||||||
return new InputInterval.Segment(min.get(), min.get()+stride);
|
return new InputInterval.Segment(min.get(), min.get() + stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,30 +84,30 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public double getProgress() {
|
// public double getProgress() {
|
||||||
return (double) (cycleValue.get() - min.get());
|
// return (double) (cycleValue.get() - min.get());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public double getTotal() {
|
// public double getTotal() {
|
||||||
return (double) (max.get() - min.get());
|
// return (double) (max.get() - min.get());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public String getProgressDetails() {
|
// public AtomicInputProgress.Range getRange() {
|
||||||
return "min=" +min.get() + " cycle=" + cycleValue.get() + " max=" + max.get() +
|
// return new Range(this);
|
||||||
(recycleMax.get()>0L ? " recycles=" + recycleValue.get() +"/" + recycleMax.get() : "");
|
// }
|
||||||
}
|
//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AtomicInput{" +
|
return "AtomicInput{" +
|
||||||
"cycleValue=" + cycleValue +
|
"cycleValue=" + cycleValue +
|
||||||
", min=" + min +
|
", min=" + min +
|
||||||
", max=" + max +
|
", max=" + max +
|
||||||
", activity=" + activityDef.getAlias() +
|
", activity=" + activityDef.getAlias() +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,7 +136,10 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
|||||||
|
|
||||||
long recycles = activityDef.getParams().getOptionalString("recycles").flatMap(Unit::longCountFor).orElse(0L);
|
long recycles = activityDef.getParams().getOptionalString("recycles").flatMap(Unit::longCountFor).orElse(0L);
|
||||||
this.recycleMax.set(recycles);
|
this.recycleMax.set(recycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStarteAtMillis() {
|
||||||
|
return this.startedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -142,4 +147,53 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AtomicInputProgress getProgressMeter() {
|
||||||
|
return new AtomicInputProgress(activityDef.getAlias(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AtomicInputProgress implements ProgressMeter {
|
||||||
|
private final AtomicInput input;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public AtomicInputProgress(String name, AtomicInput input) {
|
||||||
|
this.name = name;
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProgressName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getStartedAtMillis() {
|
||||||
|
return input.getStarteAtMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getProgressMin() {
|
||||||
|
return input.min.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getProgressCurrent() {
|
||||||
|
return input.cycleValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getProgressMax() {
|
||||||
|
return input.max.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRecyclesCurrent() {
|
||||||
|
return input.recycleValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRecyclesMax() {
|
||||||
|
return input.recycleMax.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
package io.nosqlbench.engine.api.activityimpl.input;
|
package io.nosqlbench.engine.api.activityimpl.input;
|
||||||
|
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.ProgressMeter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Any type that implements this interface can provide a double indicating relative progress.
|
* Any type that implements this interface can provide a double indicating relative progress.
|
||||||
*/
|
*/
|
||||||
public interface ProgressCapable {
|
public interface ProgressCapable {
|
||||||
double getProgress();
|
ProgressMeter getProgressMeter();
|
||||||
double getTotal();
|
|
||||||
String getProgressDetails();
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package io.nosqlbench.engine.api.activityimpl.input;
|
||||||
|
|
||||||
|
import io.nosqlbench.engine.api.activityapi.core.RunState;
|
||||||
|
|
||||||
|
public interface StateCapable {
|
||||||
|
RunState getRunState();
|
||||||
|
}
|
@ -315,7 +315,7 @@ public class NBCLIScenarioParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String description = stmts.getDescription();
|
String description = stmts.getDescription();
|
||||||
workloadDescriptions.add(new WorkloadDesc(referenced, scenarioNames, sortedTemplates, description,""));
|
workloadDescriptions.add(new WorkloadDesc(referenced, scenarioNames, sortedTemplates, description, ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Collections.sort(workloadDescriptions);
|
Collections.sort(workloadDescriptions);
|
||||||
@ -324,11 +324,15 @@ public class NBCLIScenarioParser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<WorkloadDesc> getWorkloadsWithScenarioScripts(boolean defaultIncludes, Set<String> includes) {
|
||||||
|
return getWorkloadsWithScenarioScripts(defaultIncludes, includes.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
public static List<WorkloadDesc> getWorkloadsWithScenarioScripts(boolean defaultIncludes, String... includes) {
|
public static List<WorkloadDesc> getWorkloadsWithScenarioScripts(boolean defaultIncludes, String... includes) {
|
||||||
|
|
||||||
NBPathsAPI.GetPrefix searchin = NBIO.all();
|
NBPathsAPI.GetPrefix searchin = NBIO.all();
|
||||||
if (defaultIncludes) {
|
if (defaultIncludes) {
|
||||||
searchin= searchin.prefix(SEARCH_IN);
|
searchin = searchin.prefix(SEARCH_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Content<?>> activities = searchin
|
List<Content<?>> activities = searchin
|
||||||
|
@ -48,10 +48,13 @@ public class WorkloadDesc implements Comparable<WorkloadDesc> {
|
|||||||
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toString(true);
|
return
|
||||||
|
((workspace != null && !workspace.isEmpty()) ? workspace + ":" : "")
|
||||||
|
+ this.yamlPath;
|
||||||
|
// + (this.description != null ? "\ndesc: " + this.description : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString(boolean includeScenarios) {
|
public String toMarkdown(boolean includeScenarios) {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
@ -61,10 +64,10 @@ public class WorkloadDesc implements Comparable<WorkloadDesc> {
|
|||||||
|
|
||||||
if (!description.isEmpty()) {
|
if (!description.isEmpty()) {
|
||||||
// sb.append("# description:\n");
|
// sb.append("# description:\n");
|
||||||
String formttedDesc = "# " + String.join("\n# ",description.split("\n"));
|
String formttedDesc = "# " + String.join("\n# ", description.split("\n"));
|
||||||
sb.append(formttedDesc).append("\n");
|
sb.append(formttedDesc).append("\n");
|
||||||
while (sb.toString().endsWith("\n\n")) {
|
while (sb.toString().endsWith("\n\n")) {
|
||||||
sb.setLength(sb.length()-1);
|
sb.setLength(sb.length() - 1);
|
||||||
}
|
}
|
||||||
// if (!description.endsWith("\n")) {
|
// if (!description.endsWith("\n")) {
|
||||||
// sb.append("\n");
|
// sb.append("\n");
|
||||||
@ -124,4 +127,5 @@ public class WorkloadDesc implements Comparable<WorkloadDesc> {
|
|||||||
public String getWorkspace() {
|
public String getWorkspace() {
|
||||||
return workspace;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,16 @@
|
|||||||
|
|
||||||
package io.nosqlbench.engine.api.util;
|
package io.nosqlbench.engine.api.util;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
import java.io.File;
|
import org.slf4j.Logger;
|
||||||
import java.io.FileInputStream;
|
import org.slf4j.LoggerFactory;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import javax.net.ServerSocketFactory;
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import java.io.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
@ -33,16 +38,6 @@ import java.security.spec.PKCS8EncodedKeySpec;
|
|||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.net.ServerSocketFactory;
|
|
||||||
import javax.net.SocketFactory;
|
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
|
||||||
|
|
||||||
public class SSLKsFactory {
|
public class SSLKsFactory {
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SSLKsFactory.class);
|
private final static Logger logger = LoggerFactory.getLogger(SSLKsFactory.class);
|
||||||
@ -186,7 +181,7 @@ public class SSLKsFactory {
|
|||||||
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||||
kmf.init(keyStore, keyPassword);
|
kmf.init(keyStore, keyPassword);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Unable to init KeyManagerFactory. Please check.", e);
|
throw new RuntimeException("Unable to init KeyManagerFactory. Please check password and location.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
TrustManagerFactory tmf;
|
TrustManagerFactory tmf;
|
||||||
|
@ -12,7 +12,7 @@ public class NBCLIScenarios {
|
|||||||
NBCLIScenarioParser.getWorkloadsWithScenarioScripts(true, includes);
|
NBCLIScenarioParser.getWorkloadsWithScenarioScripts(true, includes);
|
||||||
|
|
||||||
for (WorkloadDesc workload : workloads) {
|
for (WorkloadDesc workload : workloads) {
|
||||||
System.out.println(workload.toString(includeScenarios));
|
System.out.println(workload.toMarkdown(includeScenarios));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!includeScenarios) {
|
if (!includeScenarios) {
|
||||||
|
@ -15,10 +15,8 @@
|
|||||||
package io.nosqlbench.engine.core;
|
package io.nosqlbench.engine.core;
|
||||||
|
|
||||||
import io.nosqlbench.engine.api.activityapi.core.*;
|
import io.nosqlbench.engine.api.activityapi.core.*;
|
||||||
import io.nosqlbench.engine.api.activityapi.input.Input;
|
|
||||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
||||||
import io.nosqlbench.engine.api.activityimpl.SlotStateTracker;
|
|
||||||
import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable;
|
import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -46,7 +44,7 @@ import java.util.stream.Collectors;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ActivityExecutor implements ActivityController, ParameterMap.Listener, ProgressMeter {
|
public class ActivityExecutor implements ActivityController, ParameterMap.Listener, ProgressCapable {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ActivityExecutor.class);
|
private static final Logger logger = LoggerFactory.getLogger(ActivityExecutor.class);
|
||||||
private static final Logger activitylogger = LoggerFactory.getLogger("ACTIVITY");
|
private static final Logger activitylogger = LoggerFactory.getLogger("ACTIVITY");
|
||||||
@ -121,14 +119,7 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public synchronized RuntimeException forceStopScenario(int initialMillisToWait) {
|
||||||
* Shutdown the activity executor, with a grace period for the motor threads.
|
|
||||||
*
|
|
||||||
* @param initialMillisToWait milliseconds to wait after graceful shutdownActivity request, before forcing
|
|
||||||
* everything to stop
|
|
||||||
*/
|
|
||||||
public synchronized void forceStopExecutor(int initialMillisToWait) {
|
|
||||||
|
|
||||||
activitylogger.debug("FORCE STOP/before alias=(" + activity.getAlias() + ")");
|
activitylogger.debug("FORCE STOP/before alias=(" + activity.getAlias() + ")");
|
||||||
|
|
||||||
activity.setRunState(RunState.Stopped);
|
activity.setRunState(RunState.Stopped);
|
||||||
@ -164,15 +155,28 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
activity.closeAutoCloseables();
|
activity.closeAutoCloseables();
|
||||||
long activityShutdownEndedAt = System.currentTimeMillis();
|
long activityShutdownEndedAt = System.currentTimeMillis();
|
||||||
logger.debug("took " + (activityShutdownEndedAt - activityShutdownStartedAt) + " ms to shutdown activity threads");
|
logger.debug("took " + (activityShutdownEndedAt - activityShutdownStartedAt) + " ms to shutdown activity threads");
|
||||||
|
activitylogger.debug("FORCE STOP/after alias=(" + activity.getAlias() + ")");
|
||||||
|
|
||||||
if (stoppingException != null) {
|
if (stoppingException != null) {
|
||||||
activitylogger.debug("FORCE STOP/exception alias=(" + activity.getAlias() + ")");
|
activitylogger.debug("FORCE STOP/exception alias=(" + activity.getAlias() + ")");
|
||||||
throw stoppingException;
|
|
||||||
}
|
}
|
||||||
activitylogger.debug("FORCE STOP/after alias=(" + activity.getAlias() + ")");
|
return stoppingException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the activity executor, with a grace period for the motor threads.
|
||||||
|
*
|
||||||
|
* @param initialMillisToWait milliseconds to wait after graceful shutdownActivity request, before forcing
|
||||||
|
* everything to stop
|
||||||
|
*/
|
||||||
|
public synchronized void forceStopScenarioAndThrow(int initialMillisToWait, boolean rethrow) {
|
||||||
|
RuntimeException exception = forceStopScenario(initialMillisToWait);
|
||||||
|
if (exception != null && rethrow) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean requestStopExecutor(int secondsToWait) {
|
public boolean requestStopExecutor(int secondsToWait) {
|
||||||
activitylogger.debug("REQUEST STOP/before alias=(" + activity.getAlias() + ")");
|
activitylogger.debug("REQUEST STOP/before alias=(" + activity.getAlias() + ")");
|
||||||
|
|
||||||
@ -465,61 +469,10 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
return activity;
|
return activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized double getProgress() {
|
|
||||||
ArrayList<Input> inputs = motors.stream()
|
|
||||||
.map(Motor::getInput)
|
|
||||||
.distinct()
|
|
||||||
.collect(Collectors.toCollection(ArrayList::new));
|
|
||||||
|
|
||||||
double startCycle = getActivityDef().getStartCycle();
|
|
||||||
double endCycle = getActivityDef().getEndCycle();
|
|
||||||
double totalCycles = endCycle - startCycle;
|
|
||||||
|
|
||||||
double total = 0.0D;
|
|
||||||
double progress = 0.0D;
|
|
||||||
|
|
||||||
for (Input input : inputs) {
|
|
||||||
if (input instanceof ProgressCapable) {
|
|
||||||
ProgressCapable progressInput = (ProgressCapable) input;
|
|
||||||
total += progressInput.getTotal();
|
|
||||||
progress += progressInput.getProgress();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
logger.warn("input does not support activity progress: " + input);
|
|
||||||
return Double.NaN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return progress / total;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProgressDetails() {
|
|
||||||
return motors.stream().map(Motor::getInput).distinct().findFirst()
|
|
||||||
.filter(i -> i instanceof ProgressCapable)
|
|
||||||
.map(i -> ((ProgressCapable) i).getProgressDetails()).orElse("");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getProgressName() {
|
|
||||||
return activityDef.getAlias();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RunState getProgressState() {
|
|
||||||
Optional<RunState> first = motors.stream()
|
|
||||||
.map(Motor::getSlotStateTracker).map(SlotStateTracker::getSlotState)
|
|
||||||
.distinct().sorted().findFirst();
|
|
||||||
return first.orElse(RunState.Uninitialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized void notifyException(Thread t, Throwable e) {
|
public synchronized void notifyException(Thread t, Throwable e) {
|
||||||
//logger.error("Uncaught exception in activity thread forwarded to activity executor:", e);
|
//logger.error("Uncaught exception in activity thread forwarded to activity executor:", e);
|
||||||
this.stoppingException = new RuntimeException("Error in activity thread " + t.getName(), e);
|
this.stoppingException = new RuntimeException("Error in activity thread " + t.getName(), e);
|
||||||
forceStopExecutor(10000);
|
forceStopScenario(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -544,4 +497,11 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
}
|
}
|
||||||
requestStopMotors();
|
requestStopMotors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProgressMeter getProgressMeter() {
|
||||||
|
return this.activity.getProgressMeter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
package io.nosqlbench.engine.core;
|
package io.nosqlbench.engine.core;
|
||||||
|
|
||||||
import io.nosqlbench.engine.api.activityapi.core.ProgressMeter;
|
|
||||||
import io.nosqlbench.engine.api.activityapi.core.RunState;
|
import io.nosqlbench.engine.api.activityapi.core.RunState;
|
||||||
|
import io.nosqlbench.engine.api.activityimpl.ProgressAndStateMeter;
|
||||||
import io.nosqlbench.engine.api.metrics.IndicatorMode;
|
import io.nosqlbench.engine.api.metrics.IndicatorMode;
|
||||||
import io.nosqlbench.engine.api.metrics.PeriodicRunnable;
|
import io.nosqlbench.engine.api.metrics.PeriodicRunnable;
|
||||||
import io.nosqlbench.engine.api.util.Unit;
|
import io.nosqlbench.engine.api.util.Unit;
|
||||||
@ -30,18 +30,18 @@ import java.util.HashSet;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ProgressIndicator implements Runnable {
|
public class ActivityProgressIndicator implements Runnable {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ProgressIndicator.class);
|
private final static Logger logger = LoggerFactory.getLogger(ActivityProgressIndicator.class);
|
||||||
private final String indicatorSpec;
|
private final String indicatorSpec;
|
||||||
private final ScenarioController sc;
|
private final ScenarioController sc;
|
||||||
private PeriodicRunnable<ProgressIndicator> runnable;
|
private PeriodicRunnable<ActivityProgressIndicator> runnable;
|
||||||
private IndicatorMode indicatorMode = IndicatorMode.console;
|
private IndicatorMode indicatorMode = IndicatorMode.console;
|
||||||
private Set<String> seen = new HashSet<>();
|
private final Set<String> seen = new HashSet<>();
|
||||||
|
|
||||||
private long intervalMillis=1L;
|
private long intervalMillis = 1L;
|
||||||
|
|
||||||
public ProgressIndicator(ScenarioController sc, String indicatorSpec) {
|
public ActivityProgressIndicator(ScenarioController sc, String indicatorSpec) {
|
||||||
this.sc = sc;
|
this.sc = sc;
|
||||||
this.indicatorSpec = indicatorSpec;
|
this.indicatorSpec = indicatorSpec;
|
||||||
start();
|
start();
|
||||||
@ -76,21 +76,22 @@ public class ProgressIndicator implements Runnable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Collection<ProgressMeter> progressMeters = sc.getProgressMeters();
|
Collection<ProgressAndStateMeter> progressMeters = sc.getProgressMeters();
|
||||||
for (ProgressMeter meter : progressMeters) {
|
for (ProgressAndStateMeter meter : progressMeters) {
|
||||||
|
|
||||||
boolean lastReport=false;
|
boolean lastReport = false;
|
||||||
if (meter.getProgress()>=1.0d || meter.getProgressState()== RunState.Finished) {
|
if (meter.getProgressRatio() >= 1.0d || meter.getRunState() == RunState.Finished) {
|
||||||
if (seen.contains(meter.getProgressName())) {
|
if (seen.contains(meter.getProgressName())) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
seen.add(meter.getProgressName());
|
seen.add(meter.getProgressName());
|
||||||
lastReport=true;
|
lastReport = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String progress = meter.getProgressName() + ": " + formatProgress(meter.getProgress()) + "/" + meter.getProgressState() +
|
String progress =
|
||||||
" (details: " + meter.getProgressDetails()+")" + (lastReport ? " (last report)" : "");
|
meter.getProgressName() + ": " + formatProgress(meter.getProgressRatio()) + "/" + meter.getRunState() +
|
||||||
|
" (details: " + meter.getProgressSummary() + ")" + (lastReport ? " (last report)" : "");
|
||||||
|
|
||||||
switch (indicatorMode) {
|
switch (indicatorMode) {
|
||||||
case console:
|
case console:
|
@ -16,11 +16,11 @@ package io.nosqlbench.engine.core;
|
|||||||
|
|
||||||
import io.nosqlbench.engine.api.activityapi.core.Activity;
|
import io.nosqlbench.engine.api.activityapi.core.Activity;
|
||||||
import io.nosqlbench.engine.api.activityapi.core.ActivityType;
|
import io.nosqlbench.engine.api.activityapi.core.ActivityType;
|
||||||
import io.nosqlbench.engine.api.activityapi.core.ProgressMeter;
|
|
||||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
||||||
import io.nosqlbench.nb.api.errors.BasicError;
|
import io.nosqlbench.engine.api.activityimpl.ProgressAndStateMeter;
|
||||||
import io.nosqlbench.engine.api.metrics.ActivityMetrics;
|
import io.nosqlbench.engine.api.metrics.ActivityMetrics;
|
||||||
|
import io.nosqlbench.nb.api.errors.BasicError;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -332,9 +332,9 @@ public class ScenarioController {
|
|||||||
*
|
*
|
||||||
* @param waitTimeMillis grace period during which an activity may cooperatively shut down
|
* @param waitTimeMillis grace period during which an activity may cooperatively shut down
|
||||||
*/
|
*/
|
||||||
public void forceStopScenario(int waitTimeMillis) {
|
public void forceStopScenario(int waitTimeMillis, boolean rethrow) {
|
||||||
logger.debug("Scenario force stopped.");
|
logger.debug("Scenario force stopped.");
|
||||||
activityExecutors.values().forEach(a -> a.forceStopExecutor(waitTimeMillis));
|
activityExecutors.values().forEach(a -> a.forceStopScenarioAndThrow(waitTimeMillis, rethrow));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -414,7 +414,11 @@ public class ScenarioController {
|
|||||||
return activityMap;
|
return activityMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ProgressMeter> getProgressMeters() {
|
public Collection<ProgressAndStateMeter> getProgressMeters() {
|
||||||
return this.activityExecutors.values().stream().map(e -> (ProgressMeter) e).collect(Collectors.toList());
|
List<ProgressAndStateMeter> indicators = new ArrayList<>();
|
||||||
|
for (ActivityExecutor ae : activityExecutors.values()) {
|
||||||
|
indicators.add(new ProgressAndStateMeter(ae.getProgressMeter(), ae.getActivity()));
|
||||||
|
}
|
||||||
|
return indicators;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,16 +26,12 @@ are automatically included when NoSQLBench is built.
|
|||||||
|
|
||||||
## NoSQLBench Slack
|
## NoSQLBench Slack
|
||||||
|
|
||||||
There is a new slack channel at nosqlbench.slack.com. In order to access the slack channel, you'll need an invite. You
|
Please click the
|
||||||
can get that through this simple form, which will send you an invite in email:
|
[Invite Link for nosqlbench.slack.com](https://join.slack.com/t/nosqlbench/shared_invite/zt-grrg64g3-6SeVi2jaum0cxp51WnvOVA)
|
||||||
[Slack Invite](https://docs.google.com/forms/d/e/1FAIpQLSdUOJ8iAPqyxsLfh1nBBsKShI53RAeuzYW4bKExmRMWjj4ufQ/viewform).
|
to join us.
|
||||||
This is just a simple google form that automates the invite process.
|
|
||||||
|
|
||||||
Please join it if you are a new or existing NoSQLBench user and help us get it going!
|
Please join it if you are a new or existing NoSQLBench user and help us get it going!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## General Feedback
|
## General Feedback
|
||||||
|
|
||||||
These guidelines are mirrored at the
|
These guidelines are mirrored at the
|
||||||
|
@ -10,6 +10,8 @@ import javax.inject.Singleton;
|
|||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.Configuration;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
@Service(WebServiceObject.class)
|
@Service(WebServiceObject.class)
|
||||||
@ -18,6 +20,9 @@ import javax.ws.rs.core.MediaType;
|
|||||||
public class ServiceStatusEndpoint implements WebServiceObject {
|
public class ServiceStatusEndpoint implements WebServiceObject {
|
||||||
private final static Logger logger = LogManager.getLogger(AutoDocsWebService.class);
|
private final static Logger logger = LogManager.getLogger(AutoDocsWebService.class);
|
||||||
|
|
||||||
|
@Context
|
||||||
|
private Configuration config;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
|
Loading…
Reference in New Issue
Block a user