├── .dockerignore ├── .env.development ├── .env.prod ├── .gitignore ├── Dockerfile ├── README.md ├── images ├── dashboard_1.PNG ├── dashboard_2.PNG ├── dashboard_3.PNG ├── dashboard_4.PNG └── dashboard_5.PNG ├── nginx-dashboard.conf ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── components │ ├── Job.vue │ ├── Menu.vue │ ├── Overview.vue │ ├── OverviewJobs.vue │ └── Run.vue ├── getEnvironmentSettings.js └── main.js ├── vue.config.js └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .git/ -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | VUE_APP_SERVICES=[{"host": "localhost", "url": "http://localhost:8081/scheduled-jobs"}] -------------------------------------------------------------------------------- /.env.prod: -------------------------------------------------------------------------------- 1 | VUE_APP_SERVICES=[{"host": "localhost", "url": "http://localhost:8081/scheduled-jobs"}] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.iml -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | #==================== Building Stage ================================================ 2 | 3 | FROM node:10.9.0-alpine as node 4 | 5 | # Create a directory where our app will be placed. This might not be necessary 6 | RUN mkdir -p /dashboard 7 | 8 | # Change directory so that our commands run inside this new directory 9 | WORKDIR /dashboard 10 | 11 | # Copy dependency definitions 12 | COPY package.json /dashboard 13 | 14 | # Install dependencies 15 | RUN yarn install 16 | 17 | # Get all the code needed to run the app 18 | COPY . /dashboard 19 | 20 | # Expose the port the app runs in 21 | EXPOSE 8080 22 | 23 | #Build the app 24 | RUN yarn build 25 | 26 | #==================== Setting up stage ==================== 27 | FROM nginx:1.15.2-alpine 28 | 29 | COPY --from=node /dashboard/dist/ /usr/share/nginx/html 30 | 31 | COPY ./nginx-dashboard.conf /etc/nginx/conf.d/default.conf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-dashboard-scheduled-tasks 2 | 3 | Dashboard to track scheduled tasks in a spring boot application. 4 | 5 | This is a dashboard based on the data retrieved via https://github.com/kevcodez/spring-boot-track-scheduled-tasks 6 | 7 | The dashboard allows the configuration of multiple services. 8 | 9 | # Images 10 | 11 | ## Overview 12 | 13 | ![Overview of the jobs](images/dashboard_1.PNG?raw=true) 14 | 15 | * Switch between environments 16 | * List of all services configured 17 | * Select a specific service to view jobs from the service 18 | * Info about latest run 19 | * Status from latest run (not run, failed, success) 20 | 21 | ## Mobile View 22 | 23 | ![Mobile view](images/dashboard_2.PNG?raw=true) 24 | 25 | ## Specific Job 26 | 27 | ![View runs from a specific job](images/dashboard_3.PNG?raw=true) 28 | 29 | * Last 10 runs with timings 30 | * Stats 31 | ** Average runtime 32 | ** Run count 33 | ** Exceptions occured 34 | * CRON settings 35 | 36 | If the job did not run yet, it looks like this: 37 | 38 | ![Specific job, when job did not run yet](images/dashboard_4.PNG?raw=true) 39 | 40 | ## Specific run 41 | 42 | ![Data from a specific run](images/dashboard_5.PNG?raw=true) 43 | 44 | * View error details 45 | * View timing 46 | 47 | # Configuration 48 | 49 | The getEnvironmentSettings.js includes the environments and URLs to the services providing scheduled task tracking data. 50 | 51 | You can configure multiple services. 52 | 53 | ```js 54 | export function getEnvironmentSettings() { 55 | return { 56 | "Test": { 57 | "baseUrl": "https://my-api.test.de/", 58 | "services": [ 59 | { 60 | "host": "Billing-Service", 61 | "url": "billing-service/scheduled-jobs" 62 | }, 63 | { 64 | "host": "Contract-Service", 65 | "url": "contract-service/scheduled-jobs" 66 | } 67 | ] 68 | }, 69 | "Production": { 70 | "baseUrl": "https://my-api.live.de/", 71 | "services": [ 72 | { 73 | "host": "Billing-Service", 74 | "url": "billing-service/scheduled-jobs" 75 | }, 76 | { 77 | "host": "Contract-Service", 78 | "url": "contract-service/scheduled-jobs" 79 | } 80 | ] 81 | } 82 | } 83 | } 84 | ``` 85 | 86 | # Features 87 | 88 | * Switch between different environments 89 | * Support for multiple services 90 | * Get an overview of all jobs 91 | * Get all jobs from a specific service 92 | * View successful, failed and jobs that did not run yet 93 | * View a run history of a any job 94 | * Trigger a job 95 | * View a specific run 96 | * View errors from jobs, of occured 97 | 98 | # Development 99 | 100 | Simple run `yarn serve` for starting a webserver with hot reload and everything you need. You should change the URLs in getEnvironmentSettings.js. 101 | 102 | For fetching data from the services, [Vue-Resource](https://github.com/pagekit/vue-resource) is used. Vue-Resource also lets you add authentication very easily. 103 | 104 | # Building for production 105 | 106 | First configure your services in the getEnvironmentSettings.js file. 107 | 108 | Build the docker image, nginx is used as server. 109 | 110 | ``` 111 | docker image build -t dashboard:latest . 112 | 113 | docker run -d -p 80:80 dashboard:latest 114 | ``` -------------------------------------------------------------------------------- /images/dashboard_1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevcodez/spring-boot-dashboard-scheduled-tasks/08c3c7165deb6019d5c2df1a537b1e224145f8db/images/dashboard_1.PNG -------------------------------------------------------------------------------- /images/dashboard_2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevcodez/spring-boot-dashboard-scheduled-tasks/08c3c7165deb6019d5c2df1a537b1e224145f8db/images/dashboard_2.PNG -------------------------------------------------------------------------------- /images/dashboard_3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevcodez/spring-boot-dashboard-scheduled-tasks/08c3c7165deb6019d5c2df1a537b1e224145f8db/images/dashboard_3.PNG -------------------------------------------------------------------------------- /images/dashboard_4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevcodez/spring-boot-dashboard-scheduled-tasks/08c3c7165deb6019d5c2df1a537b1e224145f8db/images/dashboard_4.PNG -------------------------------------------------------------------------------- /images/dashboard_5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevcodez/spring-boot-dashboard-scheduled-tasks/08c3c7165deb6019d5c2df1a537b1e224145f8db/images/dashboard_5.PNG -------------------------------------------------------------------------------- /nginx-dashboard.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | 4 | root /usr/share/nginx/html; 5 | 6 | location / { 7 | index index.html index.htm; 8 | try_files $uri $uri/ /index.html =404; 9 | } 10 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scheduled-tasks-dashboard", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "bulma": "0.7.1", 12 | "moment": "2.22.2", 13 | "vue": "2.5.17", 14 | "vue-awesome": "3.1.0", 15 | "vue-resource": "1.5.1", 16 | "vue-router": "3.0.1" 17 | }, 18 | "devDependencies": { 19 | "@vue/cli-plugin-babel": "3.0.1", 20 | "@vue/cli-plugin-eslint": "3.0.1", 21 | "@vue/cli-service": "3.0.1", 22 | "vue-template-compiler": "2.5.17" 23 | }, 24 | "babel": { 25 | "presets": [ 26 | "@vue/app" 27 | ] 28 | }, 29 | "eslintConfig": { 30 | "root": true, 31 | "extends": [ 32 | "plugin:vue/essential", 33 | "eslint:recommended" 34 | ] 35 | }, 36 | "postcss": { 37 | "plugins": { 38 | "autoprefixer": {} 39 | } 40 | }, 41 | "browserslist": [ 42 | "> 1%", 43 | "last 2 versions", 44 | "not ie <= 8" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevcodez/spring-boot-dashboard-scheduled-tasks/08c3c7165deb6019d5c2df1a537b1e224145f8db/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | scheduled-tasks-dashboard 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /src/components/Job.vue: -------------------------------------------------------------------------------- 1 | 92 | 93 | 173 | -------------------------------------------------------------------------------- /src/components/Menu.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /src/components/Overview.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | -------------------------------------------------------------------------------- /src/components/OverviewJobs.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 62 | 63 | 103 | -------------------------------------------------------------------------------- /src/components/Run.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 120 | -------------------------------------------------------------------------------- /src/getEnvironmentSettings.js: -------------------------------------------------------------------------------- 1 | export function getEnvironments() { 2 | let environmentSettings = getEnvironmentSettings(); 3 | let envs = []; 4 | for (let key in environmentSettings) { 5 | envs.push(key) 6 | } 7 | return envs 8 | } 9 | 10 | export function getEnvironment(env) { 11 | return getEnvironmentSettings()[env] 12 | } 13 | 14 | export function getCurrentEnvironmentName() { 15 | return localStorage.getItem("env") || getEnvironments()[0]; 16 | } 17 | 18 | export function getCurrentEnvironment() { 19 | let environment = getCurrentEnvironmentName(); 20 | 21 | return getEnvironment(environment) 22 | } 23 | 24 | export function getEnvironmentSettings() { 25 | return { 26 | "Test": { 27 | "baseUrl": "https://my-api.test.de/", 28 | "services": [ 29 | { 30 | "host": "Billing-Service", 31 | "url": "billing-service/scheduled-jobs" 32 | }, 33 | { 34 | "host": "Contract-Service", 35 | "url": "contract-service/scheduled-jobs" 36 | } 37 | ] 38 | }, 39 | "Production": { 40 | "baseUrl": "https://my-api.live.de/", 41 | "services": [ 42 | { 43 | "host": "Billing-Service", 44 | "url": "billing-service/scheduled-jobs" 45 | }, 46 | { 47 | "host": "Contract-Service", 48 | "url": "contract-service/scheduled-jobs" 49 | } 50 | ] 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import Overview from './components/Overview' 4 | import Job from './components/Job' 5 | import Run from './components/Run' 6 | import VueRouter from 'vue-router' 7 | import VueResource from 'vue-resource'; 8 | import 'bulma/css/bulma.css' 9 | import 'vue-awesome/icons/play-circle'; 10 | import 'vue-awesome/icons/spinner'; 11 | import 'vue-awesome/icons/check-circle'; 12 | import 'vue-awesome/icons/exclamation-circle'; 13 | import 'vue-awesome/icons/pause'; 14 | import Icon from 'vue-awesome/components/Icon'; 15 | import {getCurrentEnvironment} from "./getEnvironmentSettings"; 16 | 17 | Vue.config.productionTip = false; 18 | 19 | Vue.use(VueRouter); 20 | Vue.use(VueResource); 21 | Vue.component('icon', Icon); 22 | 23 | Vue.http.options.root = getCurrentEnvironment().baseUrl; 24 | 25 | const routes = [ 26 | {path: '/', component: Overview}, 27 | {path: '/:host', component: Overview}, 28 | {path: '/:host/:class', component: Overview}, 29 | {path: '/:host/:class/:method', component: Job}, 30 | {path: '/:host/:class/:method/:uuid', component: Run} 31 | ]; 32 | 33 | // 3. Create the router instance and pass the `routes` option 34 | // You can pass in additional options here, but let's 35 | // keep it simple for now. 36 | const router = new VueRouter({ 37 | routes 38 | }); 39 | 40 | new Vue({ 41 | router, 42 | render: h => h(App) 43 | }).$mount('#app'); 44 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | baseUrl: './' 3 | }; 4 | --------------------------------------------------------------------------------