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}) {
|
||||
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.new_workspace = "";
|
||||
this.mode = "showing";
|
||||
|
@ -45,7 +45,7 @@ export default {
|
||||
}
|
||||
|
||||
let result={namespaces: collated};
|
||||
console.log("namespaces result:"+JSON.stringify(result));
|
||||
// console.log("namespaces result:"+JSON.stringify(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
"author": "Sebastian Estevez & Jonathan Shook",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "nuxt -c nuxt.config.dev.js",
|
||||
"dev": "nuxt -c nuxt.config.dev.js --port 3003",
|
||||
"build": "nuxt build",
|
||||
"start": "nuxt start",
|
||||
"generate": "nuxt generate",
|
||||
|
@ -2,9 +2,7 @@
|
||||
<v-app>
|
||||
<main-app-bar>NoSQLBench - Workload Builder</main-app-bar>
|
||||
|
||||
<v-layout
|
||||
justify-center
|
||||
align-center>
|
||||
<v-layout>
|
||||
|
||||
<v-main>
|
||||
<v-container fluid>
|
||||
@ -62,9 +60,9 @@ import {saveAs} from "file-saver";
|
||||
import yamlDumper from "js-yaml";
|
||||
import CQL3Parser from '@/antlr/CQL3Parser.js';
|
||||
import CQL3Lexer from '@/antlr/CQL3Lexer.js';
|
||||
import defaultYaml from '~/assets/default.yaml';
|
||||
import basictypes from '@/assets/basictypes.yaml';
|
||||
import WorkspaceSelector from "~/components/WorkspaceSelector";
|
||||
import defaultYaml from 'assets/default.yaml';
|
||||
import basictypes from 'assets/basictypes.yaml';
|
||||
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
||||
import AppSelector from "@/components/AppSelector";
|
||||
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>
|
||||
|
||||
import WorkspaceSelector from "~/components/WorkspaceSelector";
|
||||
import WorkspaceSelector from "@/components/WorkspaceSelector";
|
||||
import {mapActions, mapGetters, mapMutations} from "vuex";
|
||||
import AppSelector from "@/components/AppSelector";
|
||||
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";
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -78,13 +78,6 @@ export const mutations = {
|
||||
setCategories(state, categories) {
|
||||
state.categories = categories;
|
||||
},
|
||||
// initializeStore(state) {
|
||||
// if(localStorage.getItem('store')) {
|
||||
// this.replaceState(
|
||||
// Object.assign(state,JSON.parse(localStorage.getItem('store')))
|
||||
// );
|
||||
// }
|
||||
// },
|
||||
toggleDrawerState(state, newDrawerState) {
|
||||
if (state.isMenuLocked) {
|
||||
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 = {
|
||||
async setWorkloads({commit, state, dispatch}, val) {
|
||||
console.log("committing setWorkloads:" + JSON.stringify(val));
|
||||
// console.log("committing setWorkloads:" + JSON.stringify(val));
|
||||
commit('setWorkloads', val);
|
||||
},
|
||||
async setTemplates({commit, state, dispatch}, val) {
|
||||
console.log("commiting setTemplates:" + JSON.stringify(val));
|
||||
// console.log("commiting setTemplates:" + JSON.stringify(val));
|
||||
commit("setTemplates", val);
|
||||
},
|
||||
async setSearchin({commit, state, dispatch}, val) {
|
||||
console.log("committing setsearchin:" + JSON.stringify(val));
|
||||
// console.log("committing setsearchin:" + JSON.stringify(val));
|
||||
commit('setSearchin', val);
|
||||
},
|
||||
fetchWorkloads({commit, state, dispatch}, params) {
|
||||
async fetchWorkloads({commit, state, dispatch}, params) {
|
||||
let reason = params.reason;
|
||||
let searchin = params.searchin;
|
||||
if (reason === undefined || searchin === undefined) {
|
||||
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);
|
||||
this.$axios.$get("/workloads/?searchin=" + searchin)
|
||||
.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);
|
||||
})
|
||||
.catch((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 workload = params.workload;
|
||||
let searchin = params.searchin;
|
||||
@ -71,13 +71,15 @@ export const actions = {
|
||||
}
|
||||
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 => {
|
||||
console.log("axios/vuex templates async get:" + JSON.stringify(res));
|
||||
// console.log("axios/vuex templates async get:" + JSON.stringify(res));
|
||||
dispatch("setTemplates", res);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("axios/nuxt templates async error:", e);
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
@ -3,7 +3,8 @@ import {mapGetters} from "vuex";
|
||||
|
||||
export const state = () => ({
|
||||
workspace: 'default',
|
||||
workspaces: []
|
||||
workspaces: [],
|
||||
fileview: []
|
||||
});
|
||||
|
||||
export const getters = {
|
||||
@ -12,6 +13,9 @@ export const getters = {
|
||||
},
|
||||
getWorkspaces: (state, getters) => {
|
||||
return state.workspaces;
|
||||
},
|
||||
getFileview: (state, getters) => {
|
||||
return state.fileview;
|
||||
}
|
||||
|
||||
// ...mapGetters(['workspace','workspaces'])
|
||||
@ -23,24 +27,27 @@ export const mutations = {
|
||||
},
|
||||
setWorkspaces(state, workspaces) {
|
||||
state.workspaces = workspaces;
|
||||
},
|
||||
setFileview(state, fileview) {
|
||||
state.fileview = fileview;
|
||||
}
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
async setWorkspace({commit, state, dispatch}, val) {
|
||||
console.log("committing setWorkspace:" + JSON.stringify(val));
|
||||
// console.log("committing setWorkspace:" + JSON.stringify(val));
|
||||
commit('setWorkspace', val);
|
||||
},
|
||||
async setWorkspaces({commit, state, dispatch}, val) {
|
||||
console.log("committing setWorkspaces:" + JSON.stringify(val));
|
||||
// console.log("committing setWorkspaces:" + JSON.stringify(val));
|
||||
commit('setWorkspaces', val);
|
||||
},
|
||||
async initWorkspaces({commit, state, dispatch}, reason) {
|
||||
console.log("initializing workspaces because '" + reason + "'")
|
||||
// console.log("initializing workspaces because '" + reason + "'")
|
||||
this.$axios.$get("/workspaces/")
|
||||
.then(res => {
|
||||
console.log("axios/vuex workspaces async get:" + JSON.stringify(res));
|
||||
console.log("committing setWorkspaces:" + JSON.stringify(res));
|
||||
// console.log("axios/vuex workspaces async get:" + JSON.stringify(res));
|
||||
// console.log("committing setWorkspaces:" + JSON.stringify(res));
|
||||
commit('setWorkspaces', res)
|
||||
})
|
||||
.catch((e) => {
|
||||
@ -66,7 +73,7 @@ export const actions = {
|
||||
async activateWorkspace({commit, state, dispatch}, workspace) {
|
||||
const fresh_workspace = await this.$axios.$get("/workspaces/" + workspace)
|
||||
.then(res => {
|
||||
console.log("axios/vuex workspace async get:" + JSON.stringify(res))
|
||||
// console.log("axios/vuex workspace async get:" + JSON.stringify(res))
|
||||
return res;
|
||||
})
|
||||
.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.ParameterMap;
|
||||
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.PrintWriter;
|
||||
@ -34,15 +36,17 @@ import java.util.function.Supplier;
|
||||
* 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}.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param activityController The dedicated control interface for this activity
|
||||
*/
|
||||
void setActivityController(ActivityController activityController);
|
||||
|
||||
ActivityController getActivityController();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
RunState getRunState();
|
||||
|
||||
void setRunState(RunState runState);
|
||||
|
||||
long getStartedAtMillis();
|
||||
|
||||
default void shutdownActivity() {
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,47 @@
|
||||
package io.nosqlbench.engine.api.activityapi.core;
|
||||
|
||||
public interface ProgressMeter {
|
||||
double getProgress();
|
||||
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 io.nosqlbench.engine.api.activityapi.core.*;
|
||||
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.output.OutputDispenser;
|
||||
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.yaml.OpTemplate;
|
||||
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.templating.CommandTemplate;
|
||||
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.
|
||||
*/
|
||||
public class SimpleActivity implements Activity {
|
||||
public class SimpleActivity implements Activity, ProgressCapable {
|
||||
private final static Logger logger = LoggerFactory.getLogger(SimpleActivity.class);
|
||||
|
||||
protected ActivityDef activityDef;
|
||||
private List<AutoCloseable> closeables = new ArrayList<>();
|
||||
private final List<AutoCloseable> closeables = new ArrayList<>();
|
||||
private MotorDispenser motorDispenser;
|
||||
private InputDispenser inputDispenser;
|
||||
private ActionDispenser actionDispenser;
|
||||
@ -49,6 +51,7 @@ public class SimpleActivity implements Activity {
|
||||
private ActivityController activityController;
|
||||
private ActivityInstrumentation activityInstrumentation;
|
||||
private PrintWriter console;
|
||||
private long startedAtMillis;
|
||||
|
||||
public SimpleActivity(ActivityDef activityDef) {
|
||||
this.activityDef = activityDef;
|
||||
@ -70,6 +73,14 @@ public class SimpleActivity implements Activity {
|
||||
|
||||
public synchronized void setRunState(RunState runState) {
|
||||
this.runState = runState;
|
||||
if (runState == RunState.Running) {
|
||||
this.startedAtMillis = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartedAtMillis() {
|
||||
return startedAtMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -207,6 +218,7 @@ public class SimpleActivity implements Activity {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Timer getResultTimer() {
|
||||
return ActivityMetrics.timer(getActivityDef(), "result");
|
||||
@ -399,4 +411,16 @@ public class SimpleActivity implements Activity {
|
||||
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;
|
||||
|
||||
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.input.Input;
|
||||
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 recycleMax = new AtomicLong(0L);
|
||||
private final long startedAt = System.currentTimeMillis();
|
||||
|
||||
private ActivityDef activityDef;
|
||||
private final ActivityDef activityDef;
|
||||
|
||||
public AtomicInput(ActivityDef activityDef) {
|
||||
this.activityDef = activityDef;
|
||||
@ -64,15 +66,15 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
||||
long current = this.cycleValue.get();
|
||||
long next = current + stride;
|
||||
if (next > max.get()) {
|
||||
if (recycleValue.get()>=recycleMax.get()) {
|
||||
if (recycleValue.get() >= recycleMax.get()) {
|
||||
logger.trace("Exhausted input for " + activityDef.getAlias() + " at " + current + ", recycle " +
|
||||
"count " + recycleValue.get());
|
||||
return null;
|
||||
} else {
|
||||
if (cycleValue.compareAndSet(current,min.get()+stride)) {
|
||||
if (cycleValue.compareAndSet(current, min.get() + stride)) {
|
||||
recycleValue.getAndIncrement();
|
||||
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
|
||||
public double getProgress() {
|
||||
return (double) (cycleValue.get() - min.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTotal() {
|
||||
return (double) (max.get() - min.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProgressDetails() {
|
||||
return "min=" +min.get() + " cycle=" + cycleValue.get() + " max=" + max.get() +
|
||||
(recycleMax.get()>0L ? " recycles=" + recycleValue.get() +"/" + recycleMax.get() : "");
|
||||
}
|
||||
// @Override
|
||||
// public double getProgress() {
|
||||
// return (double) (cycleValue.get() - min.get());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public double getTotal() {
|
||||
// return (double) (max.get() - min.get());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public AtomicInputProgress.Range getRange() {
|
||||
// return new Range(this);
|
||||
// }
|
||||
//
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AtomicInput{" +
|
||||
"cycleValue=" + cycleValue +
|
||||
", min=" + min +
|
||||
", max=" + max +
|
||||
", activity=" + activityDef.getAlias() +
|
||||
'}';
|
||||
"cycleValue=" + cycleValue +
|
||||
", min=" + min +
|
||||
", max=" + max +
|
||||
", activity=" + activityDef.getAlias() +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,7 +136,10 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
||||
|
||||
long recycles = activityDef.getParams().getOptionalString("recycles").flatMap(Unit::longCountFor).orElse(0L);
|
||||
this.recycleMax.set(recycles);
|
||||
}
|
||||
|
||||
public long getStarteAtMillis() {
|
||||
return this.startedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -142,4 +147,53 @@ public class AtomicInput implements Input, ActivityDefObserver, ProgressCapable
|
||||
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;
|
||||
|
||||
import io.nosqlbench.engine.api.activityapi.core.ProgressMeter;
|
||||
|
||||
/**
|
||||
* Any type that implements this interface can provide a double indicating relative progress.
|
||||
*/
|
||||
public interface ProgressCapable {
|
||||
double getProgress();
|
||||
double getTotal();
|
||||
String getProgressDetails();
|
||||
ProgressMeter getProgressMeter();
|
||||
}
|
||||
|
@ -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();
|
||||
workloadDescriptions.add(new WorkloadDesc(referenced, scenarioNames, sortedTemplates, description,""));
|
||||
workloadDescriptions.add(new WorkloadDesc(referenced, scenarioNames, sortedTemplates, description, ""));
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
||||
NBPathsAPI.GetPrefix searchin = NBIO.all();
|
||||
if (defaultIncludes) {
|
||||
searchin= searchin.prefix(SEARCH_IN);
|
||||
searchin = searchin.prefix(SEARCH_IN);
|
||||
}
|
||||
|
||||
List<Content<?>> activities = searchin
|
||||
|
@ -48,10 +48,13 @@ public class WorkloadDesc implements Comparable<WorkloadDesc> {
|
||||
|
||||
|
||||
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();
|
||||
|
||||
@ -61,10 +64,10 @@ public class WorkloadDesc implements Comparable<WorkloadDesc> {
|
||||
|
||||
if (!description.isEmpty()) {
|
||||
// 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");
|
||||
while (sb.toString().endsWith("\n\n")) {
|
||||
sb.setLength(sb.length()-1);
|
||||
sb.setLength(sb.length() - 1);
|
||||
}
|
||||
// if (!description.endsWith("\n")) {
|
||||
// sb.append("\n");
|
||||
@ -124,4 +127,5 @@ public class WorkloadDesc implements Comparable<WorkloadDesc> {
|
||||
public String getWorkspace() {
|
||||
return workspace;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,11 +17,16 @@
|
||||
|
||||
package io.nosqlbench.engine.api.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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.security.KeyFactory;
|
||||
import java.security.KeyStore;
|
||||
@ -33,16 +38,6 @@ import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
import java.util.Optional;
|
||||
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 {
|
||||
private final static Logger logger = LoggerFactory.getLogger(SSLKsFactory.class);
|
||||
@ -186,7 +181,7 @@ public class SSLKsFactory {
|
||||
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmf.init(keyStore, keyPassword);
|
||||
} 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;
|
||||
|
@ -12,7 +12,7 @@ public class NBCLIScenarios {
|
||||
NBCLIScenarioParser.getWorkloadsWithScenarioScripts(true, includes);
|
||||
|
||||
for (WorkloadDesc workload : workloads) {
|
||||
System.out.println(workload.toString(includeScenarios));
|
||||
System.out.println(workload.toMarkdown(includeScenarios));
|
||||
}
|
||||
|
||||
if (!includeScenarios) {
|
||||
|
@ -15,10 +15,8 @@
|
||||
package io.nosqlbench.engine.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.ParameterMap;
|
||||
import io.nosqlbench.engine.api.activityimpl.SlotStateTracker;
|
||||
import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -46,7 +44,7 @@ import java.util.stream.Collectors;
|
||||
* </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 activitylogger = LoggerFactory.getLogger("ACTIVITY");
|
||||
@ -121,14 +119,7 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
public synchronized RuntimeException forceStopScenario(int initialMillisToWait) {
|
||||
activitylogger.debug("FORCE STOP/before alias=(" + activity.getAlias() + ")");
|
||||
|
||||
activity.setRunState(RunState.Stopped);
|
||||
@ -164,15 +155,28 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
||||
activity.closeAutoCloseables();
|
||||
long activityShutdownEndedAt = System.currentTimeMillis();
|
||||
logger.debug("took " + (activityShutdownEndedAt - activityShutdownStartedAt) + " ms to shutdown activity threads");
|
||||
activitylogger.debug("FORCE STOP/after alias=(" + activity.getAlias() + ")");
|
||||
|
||||
if (stoppingException != null) {
|
||||
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) {
|
||||
activitylogger.debug("REQUEST STOP/before alias=(" + activity.getAlias() + ")");
|
||||
|
||||
@ -465,61 +469,10 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
||||
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) {
|
||||
//logger.error("Uncaught exception in activity thread forwarded to activity executor:", e);
|
||||
this.stoppingException = new RuntimeException("Error in activity thread " + t.getName(), e);
|
||||
forceStopExecutor(10000);
|
||||
forceStopScenario(10000);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -544,4 +497,11 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
||||
}
|
||||
requestStopMotors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProgressMeter getProgressMeter() {
|
||||
return this.activity.getProgressMeter();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,8 @@
|
||||
|
||||
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.activityimpl.ProgressAndStateMeter;
|
||||
import io.nosqlbench.engine.api.metrics.IndicatorMode;
|
||||
import io.nosqlbench.engine.api.metrics.PeriodicRunnable;
|
||||
import io.nosqlbench.engine.api.util.Unit;
|
||||
@ -30,18 +30,18 @@ import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
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 ScenarioController sc;
|
||||
private PeriodicRunnable<ProgressIndicator> runnable;
|
||||
private PeriodicRunnable<ActivityProgressIndicator> runnable;
|
||||
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.indicatorSpec = indicatorSpec;
|
||||
start();
|
||||
@ -76,21 +76,22 @@ public class ProgressIndicator implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<ProgressMeter> progressMeters = sc.getProgressMeters();
|
||||
for (ProgressMeter meter : progressMeters) {
|
||||
Collection<ProgressAndStateMeter> progressMeters = sc.getProgressMeters();
|
||||
for (ProgressAndStateMeter meter : progressMeters) {
|
||||
|
||||
boolean lastReport=false;
|
||||
if (meter.getProgress()>=1.0d || meter.getProgressState()== RunState.Finished) {
|
||||
boolean lastReport = false;
|
||||
if (meter.getProgressRatio() >= 1.0d || meter.getRunState() == RunState.Finished) {
|
||||
if (seen.contains(meter.getProgressName())) {
|
||||
continue;
|
||||
} else {
|
||||
seen.add(meter.getProgressName());
|
||||
lastReport=true;
|
||||
lastReport = true;
|
||||
}
|
||||
}
|
||||
|
||||
String progress = meter.getProgressName() + ": " + formatProgress(meter.getProgress()) + "/" + meter.getProgressState() +
|
||||
" (details: " + meter.getProgressDetails()+")" + (lastReport ? " (last report)" : "");
|
||||
String progress =
|
||||
meter.getProgressName() + ": " + formatProgress(meter.getProgressRatio()) + "/" + meter.getRunState() +
|
||||
" (details: " + meter.getProgressSummary() + ")" + (lastReport ? " (last report)" : "");
|
||||
|
||||
switch (indicatorMode) {
|
||||
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.ActivityType;
|
||||
import io.nosqlbench.engine.api.activityapi.core.ProgressMeter;
|
||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||
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.nb.api.errors.BasicError;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -332,9 +332,9 @@ public class ScenarioController {
|
||||
*
|
||||
* @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.");
|
||||
activityExecutors.values().forEach(a -> a.forceStopExecutor(waitTimeMillis));
|
||||
activityExecutors.values().forEach(a -> a.forceStopScenarioAndThrow(waitTimeMillis, rethrow));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -414,7 +414,11 @@ public class ScenarioController {
|
||||
return activityMap;
|
||||
}
|
||||
|
||||
public Collection<ProgressMeter> getProgressMeters() {
|
||||
return this.activityExecutors.values().stream().map(e -> (ProgressMeter) e).collect(Collectors.toList());
|
||||
public Collection<ProgressAndStateMeter> getProgressMeters() {
|
||||
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
|
||||
|
||||
There is a new slack channel at nosqlbench.slack.com. In order to access the slack channel, you'll need an invite. You
|
||||
can get that through this simple form, which will send you an invite in email:
|
||||
[Slack Invite](https://docs.google.com/forms/d/e/1FAIpQLSdUOJ8iAPqyxsLfh1nBBsKShI53RAeuzYW4bKExmRMWjj4ufQ/viewform).
|
||||
This is just a simple google form that automates the invite process.
|
||||
Please click the
|
||||
[Invite Link for nosqlbench.slack.com](https://join.slack.com/t/nosqlbench/shared_invite/zt-grrg64g3-6SeVi2jaum0cxp51WnvOVA)
|
||||
to join us.
|
||||
|
||||
Please join it if you are a new or existing NoSQLBench user and help us get it going!
|
||||
|
||||
|
||||
|
||||
|
||||
## General Feedback
|
||||
|
||||
These guidelines are mirrored at the
|
||||
|
@ -10,6 +10,8 @@ import javax.inject.Singleton;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Configuration;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
@Service(WebServiceObject.class)
|
||||
@ -18,6 +20,9 @@ import javax.ws.rs.core.MediaType;
|
||||
public class ServiceStatusEndpoint implements WebServiceObject {
|
||||
private final static Logger logger = LogManager.getLogger(AutoDocsWebService.class);
|
||||
|
||||
@Context
|
||||
private Configuration config;
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public boolean isEnabled() {
|
||||
|
Loading…
Reference in New Issue
Block a user