diff --git a/grails-app/assets/javascripts/app/app.js b/grails-app/assets/javascripts/app/app.js index 8b4ccfd..f05cebb 100644 --- a/grails-app/assets/javascripts/app/app.js +++ b/grails-app/assets/javascripts/app/app.js @@ -5,7 +5,6 @@ import UserService from "./services/user-service"; import ApplicationService from "./services/application-service"; import ErrorService from "./services/error-service"; import DeploymentService from "./services/deployment-service"; -import MonitoringService from "./services/monitoring-service"; import SettingsService from "./services/settings-service"; const EventEmitter = require('events').EventEmitter; @@ -37,7 +36,6 @@ export default class App { this.applicationService = new ApplicationService(this.emitter, this.baseUrl); this.errorService = new ErrorService(this.emitter, this.baseUrl); this.deploymentService = new DeploymentService(this.emitter, this.baseUrl); - this.monitoringService = new MonitoringService(this.emitter, this.baseUrl); this.settingsService = new SettingsService(this.emitter, this.baseUrl); this.emitter.on(AppEvents.PAUSE_STATE_CHANGED, (paused) => { diff --git a/grails-app/assets/javascripts/app/components/errors/entry-histogram.js b/grails-app/assets/javascripts/app/components/errors/entry-histogram.js index f8f16f8..c006fa1 100644 --- a/grails-app/assets/javascripts/app/components/errors/entry-histogram.js +++ b/grails-app/assets/javascripts/app/components/errors/entry-histogram.js @@ -2,6 +2,7 @@ import React from "react"; import BaseComponent from "../tools/base-component"; import {LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid} from "recharts"; import LoadingHero from "../tools/loading-hero"; +import Hero from "../tools/hero"; const moment = require('moment'); export default class EntryHistogram extends BaseComponent { @@ -10,14 +11,15 @@ export default class EntryHistogram extends BaseComponent { this.state = { data: [], - first: true + first: true, + loading: true }; this._bindThis('loadObjectsFromServer') } loadObjectsFromServer() { this.getErrorService().histogram(this.props.entryGroup).then(json => { - this.updateState({data: json.data, first: false}) + this.updateState({data: json.data, first: false, loading: false}) }); } @@ -31,21 +33,24 @@ export default class EntryHistogram extends BaseComponent { } render() { - const {data, first} = this.state; - if (data.length == 0) { + const {data, first, loading} = this.state; + if (loading) { return + } else if (data.length == 0) { + return

No Data found

+ } else { + return ( + + + + }/> + + }/> + + + + ) } - return ( - - - - }/> - - }/> - - - - ) } diff --git a/grails-app/assets/javascripts/app/components/main.js b/grails-app/assets/javascripts/app/components/main.js index 1c49782..6b967ee 100644 --- a/grails-app/assets/javascripts/app/components/main.js +++ b/grails-app/assets/javascripts/app/components/main.js @@ -5,9 +5,6 @@ const AppEvents = require('../events/application-events'); // const EntryDetails = require('./entry-groups/entry-details.jsx'); import React from "react"; import AppSettings from "./settings/settings"; -import MonitoringDetails from "./monitorings/monitoring-details"; -import MonitoringAdd from "./monitorings/monitoring-add"; -import MonitoringList from "./monitorings/monitoring-list"; import EntryDetails from "./errors/entry-details"; import ErrorList from "./errors/error-list"; import AppSettingsForm from "./application/application-settings"; @@ -53,11 +50,7 @@ var Main = React.createClass({ '/applications/:id': 'applicationDetails', '/users/': 'listUser', '/users/add': 'addUser', - '/users/:id': 'userDetails', - '/monitorings/add/:type': 'monitoringsAddType', - '/monitorings/add': 'monitoringsAdd', - '/monitorings/:id': 'monitoringsDetails', - '/monitorings': 'monitoringList', + '/users/:id': 'userDetails' }, @@ -131,29 +124,6 @@ var Main = React.createClass({ return ; }, - monitoringList: function () { - this.setAction('monitorings'); - return ; - }, - - monitoringsAdd: function () { - this.setAction('monitorings'); - return ; - }, - - monitoringsAddType: function (type) { - this.setAction('monitorings'); - if (type !== 'server' && type !== 'service') { - return ('404'); - } - return - }, - - monitoringsDetails: function (id) { - this.setAction('monitorings'); - return - }, - login: function () { this.setAction('login'); return ; diff --git a/grails-app/assets/javascripts/app/components/monitorings/histogram.js b/grails-app/assets/javascripts/app/components/monitorings/histogram.js deleted file mode 100644 index 5e3c245..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/histogram.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -import React from "react"; -import FromNow from "../tools/from-now"; -import * as _ from 'lodash'; -var LineChart = require('react-chartjs').Line; - -var ServerHistorgram = React.createClass({ - - _buildDataSet: function (labels, data) { - return { - labels: labels, - datasets: [ - { - label: 'last 20 pings', - fillColor: 'rgba(220,220,220,0.2)', - strokeColor: 'rgba(220,220,220,1)', - pointColor: 'rgba(220,220,220,1)', - pointStrokeColor: '#fff', - pointHighlightFill: '#fff', - pointHighlightStroke: 'rgba(220,220,220,1)', - data: data - } - ] - } - }, - - _buildLabels: function (server) { - return _.map(server.latestPings, (ping)=> { - return ping.dateCreated - }); - }, - - _buildValues: function (server) { - return _.map(server.latestPings, (ping)=> { - return ping.responseTime - }); - }, - - render: function () { - var server = this.props.server; - var labels = this._buildLabels(server) - var values = this._buildValues(server) - var dataSet = this._buildDataSet(labels, values) - return ( -
- -
- ); - } -}); -module.exports = ServerHistorgram; - diff --git a/grails-app/assets/javascripts/app/components/monitorings/icon.jsx b/grails-app/assets/javascripts/app/components/monitorings/icon.jsx deleted file mode 100644 index b5bccc7..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/icon.jsx +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -import React from "react"; -var cx = require('classnames'); - -var MonitoringIcon = React.createClass({ - - render: function () { - var classes = cx('fa', { - 'fa-server': this.props.type === 'SERVER', - 'fa-globe': this.props.type === 'SERVICE' - }) - return () - } -}); -module.exports = MonitoringIcon; diff --git a/grails-app/assets/javascripts/app/components/monitorings/monitoring-add.js b/grails-app/assets/javascripts/app/components/monitorings/monitoring-add.js deleted file mode 100644 index d4fd3e7..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/monitoring-add.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict'; - -import * as _ from 'lodash'; -var MonitoringIcon = require('./icon.jsx'); - -import React from "react"; -import Icon from "../tools/icon"; -import BaseComponent from "../tools/base-component"; - -export default class MonitoringAdd extends BaseComponent { - - constructor(props) { - super(props) - } - - render() { - return ( -
-
-
-
-

Server

-

Simple ICMP pings ~ once a minute

-

Tests if Server is reachable and logs latency.

-

{ - this.navigate('/monitorings/add/server') - }} role="button">Choose

-
-
- -
-
-
-
-

Service Monitoring

-

HTTP Head requests to a specified URL ~ once a minute.

-

Tests HTTP response code and logs response times. We are working on detailed response checks and logs!

-

{ - this.navigate('/monitorings/add/service') - }} role="button">Choose

-
-
-
-
- ) - } - -} diff --git a/grails-app/assets/javascripts/app/components/monitorings/monitoring-details.js b/grails-app/assets/javascripts/app/components/monitorings/monitoring-details.js deleted file mode 100644 index 4a4f724..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/monitoring-details.js +++ /dev/null @@ -1,122 +0,0 @@ -'use strict'; - -var Icon = require('./icon.jsx'); -var swal = require('sweetalert'); - -import React from "react"; -import LoadingHero from "../tools/loading-hero"; -import ServiceChecksList from "./service-checks-list"; -import ServiceForm from "./service-form"; -import ServerForm from "./server-form"; -import BaseComponent from "../tools/base-component"; - -export default class MonitoringDetails extends BaseComponent { - - constructor(props) { - super(props) - - - this.state = { - monitoring: { - type: (props.type || "server").toUpperCase() - }, - errors: [], - saved: false, - dirty: false - } - - this._bindThis('onValueChange', 'onDelete', 'onSave', 'loadObjectFromServer') - if (props.id > 0) { - this.loadObjectFromServer(); - } - } - - loadObjectFromServer() { - this.getMonitoringService().get(this.props.id).then((json) => { - this.setState(_.assign(this.state, { - monitoring: json.monitoring - })) - }) - } - - onSave(e) { - e.preventDefault(); - let monitoring = this.state.monitoring; - if (monitoring.enabled === undefined) { - monitoring.enabled = false - } - this.getMonitoringService().save(monitoring); - } - - onDelete() { - swal({ - title: 'Are you sure you want to delete this?', - text: 'This action cannot be undone', - type: 'warning', - showCancelButton: true, - confirmButtonText: 'Yes', - cancelButtonText: 'No!', - }, ()=> { - this.getMonitoringService().del(this.state.monitoring).then(()=> { - this.navigate("/monitorings/") - }) - } - ) - } - - onValueChange(field, value) { - this.state.monitoring[field] = value - this.state.dirty = true - this.setState(this.state) - } - - render() { - // initial loading - const {monitoring, errors, dirty, saved} = this.state; - if (this.props.id > 0 && !monitoring.id) { - return ( - - ); - } - let form = '' - let type = '' - let hostString = null - - if (monitoring.type === 'SERVER') { - form = - type = 'Server' - hostString = monitoring.hostname - - } else if (monitoring.type === 'SERVICE') { - form = - type = 'Service' - hostString = monitoring.url - } - - let checksRow = "" - if (monitoring.id) { - checksRow = (
-
- -
-
) - } - return ( -
-
-
-

 {monitoring.name || type}  - ({hostString || 'Add a new ' + type}) -

- {form} -
-
-
- {checksRow} -
- ) - } - -} diff --git a/grails-app/assets/javascripts/app/components/monitorings/monitoring-list-row.js b/grails-app/assets/javascripts/app/components/monitorings/monitoring-list-row.js deleted file mode 100644 index 4c5a500..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/monitoring-list-row.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; - -import React from "react"; -import FromNow from "../tools/from-now"; -import BaseComponent from "../tools/base-component"; -// var LineChart = require("react-chartjs").Line; -var cx = require('classnames'); -var NavigatesMixin = require('../mixins/navigates-mixin'); - -export default class MonitoringListRow extends BaseComponent { - - constructor(props) { - super(props) - } - - render() { - const monitoring = this.props.monitoring; - - let avg = monitoring.averageResponseTime; - var pingTimeClasses = cx('ping-times', {hidden: !monitoring.enabled}); - let lastSeen = 'never' - if (monitoring.lastSuccess) { - lastSeen = - } - - let checkResult = ( - - - - - ) - checkResult = '' - if (monitoring.type === 'SERVICE') { - // checkResult = (
{countGood} of {monitoring.latestChecks.length} good checks
) - } - let pingResult = (
0 && avg <= this._consideredBadResponseTime, - 'yellow': avg > this._consideredBadResponseTime - })}>{monitoring.averageResponseTime}ms
) - - var rowClass = cx('list-row', monitoring.status.toLowerCase(), {disabled: !monitoring.enabled}) - let hostString = null - if (monitoring.type === 'SERVER') { - hostString = monitoring.hostname - } else if (monitoring.type === 'SERVICE') { - hostString = monitoring.url - } - return ( -
{ - this.navigate(`/monitorings/${monitoring.id}`) - }}> -
-

{monitoring.name} - ({hostString}) -

- - last seen: {lastSeen} - -
-
- {checkResult} -
-
- {pingResult} -
-
- ); - } - -} -// TODO: the numbers in here should be configurable! -var MonitoringListItem = React.createClass({ - - mixins: [NavigatesMixin], - - _consideredBadResponseTime: 5000, - - _onRowClicked: function () { - this._navigate(`/monitorings/details/${this.props.monitoring.id}`); - }, - - render: function () { - - } -}); -module.exports = MonitoringListItem; diff --git a/grails-app/assets/javascripts/app/components/monitorings/monitoring-list.js b/grails-app/assets/javascripts/app/components/monitorings/monitoring-list.js deleted file mode 100644 index d9f4d3f..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/monitoring-list.js +++ /dev/null @@ -1,235 +0,0 @@ -'use strict'; - -import * as _ from 'lodash'; - -var cx = require('classnames'); - -import React from "react"; -import MonitoringListRow from "./monitoring-list-row"; -import LoadingHero from "../tools/loading-hero"; -import BaseComponent from "../tools/base-component"; -import ReactPaginate from "react-paginate"; - -export default class MonitoringList extends BaseComponent { - - constructor(props) { - super(props) - - this.state = { - monitorings: null, - unfilteredTotal: -1, - showDisabled: false, - type: null, - status: null - } - - this._bindThis('loadObjectsFromServer') - } - - componentWillReceiveProps(newProps) { - if (!this.props.urlParameters || _.get(newProps.urlParameters, 'offset') !== `${this.getOffset()}`) { - this.loadObjectsFromServer(newProps.urlParameters) - } - } - - componentWillUnmount() { - this.stopInterval(); - } - - componentDidMount() { - this.setInterval(this.loadObjectsFromServer, 5000); - } - - _toggleShowDisabled() { - this.state.showDisabled = !this.state.showDisabled - this.setState(this.state) - this.loadObjectsFromServer() - } - - _toggleTypeFilter(e) { - var target = e.target - if (target.nodeName === 'I') { - target = target.parentElement - } - var type = target.getAttribute('data-type') - if (this.state.type === type) { - this.state.type = null; - } else { - this.state.type = type; - } - this.setState(this.state) - this.loadObjectsFromServer(); - } - - _toggleStatusFilter() { - switch (this.state.status) { - case 'green' : - this.state.status = null - break - case 'yellow' : - this.state.status = 'green' - break - case 'red' : - this.state.status = 'yellow' - break - default : - this.state.status = 'red' - } - this.setState(this.state) - this.loadObjectsFromServer() - } - - _clearFilters() { - this.state.type = null; - this.state.status = null; - this.state.showDisabled = false; - this.setState(this.state); - this.loadObjectsFromServer(); - } - - componentWillMount() { - this._clearFilters() - this.loadObjectsFromServer(true); - } - - componentDidMount() { - this.setInterval(this.loadObjectsFromServer, 10000); - } - - loadObjectsFromServer(props) { - let offset = _.get(props, 'offset') || this.getOffset(); - let max = _.get(props, 'max') || this.getMax(); - - this.getMonitoringService().list({offset, max}) - .then(json=> { - if (json.monitorings.length === 0 && offset > 0) { - this.navigate("/monitorings/") - } else { - this.setState(_.assign(this.state, { - monitorings: json.monitorings, - unfilteredTotal: json.unfilteredTotal, - total: json.total, - loading: false - })) - } - }); - } - - changePage(pageObj) { - if (!this.state.loading) { - let max = this.getMax(); - let offset = pageObj.selected * max; - this.navigate(`/monitorings/?${querystring.stringify({max, offset})}`); - } - } - - render() { - const {loading, monitorings, unfilteredTotal, total} = this.state - let offset = this.getOffset(); - let max = this.getMax(); - if (unfilteredTotal === -1) { - return - } else if (unfilteredTotal === 0) { - return ( -
-
-
-

Nothing is currently monitored.

-

You can start monitoring by setting up a new target

-

- { - this.navigate('/monitorings/add') - }} role="button"> -  Setup -

-
-
-
- ) - } - var rows = _.map(monitorings, (server)=> { - return - }); - - var showDisabledButtonClasses = cx('btn', { - 'btn-default': !this.state.showDisabled, - 'btn-success': this.state.showDisabled - }) - var buttons = [] - buttons.push() - buttons.push() - _.each(['SERVER', 'SERVICE'], (type) => { - var clazzes = cx('btn', { - 'btn-default': this.state.type != type, - 'btn-success': this.state.type == type - }) - var icon - switch (type) { - case 'SERVER' : - icon = ( - - ); - break; - case 'SERVICE' : - icon = ( - - ); - break; - default : - icon = type; - } - buttons.push() - }) - let statusButtonClasses = cx('btn', { - 'btn-default': this.state.status === null, - 'btn-success': this.state.status === 'green', - 'btn-warn': this.state.status === 'yellow', - 'btn-danger': this.state.status === 'red' - }) - buttons.push() - buttons.push() - - return ( -
-
- -
-
- {buttons} -
-
-
- ...} - marginPagesDisplayed={5} - activeClassName="active" - containerClassName="pagination" - /> -
-
-
-
- {rows} -
-
-
- ); - } -} diff --git a/grails-app/assets/javascripts/app/components/monitorings/server-form.js b/grails-app/assets/javascripts/app/components/monitorings/server-form.js deleted file mode 100644 index 78d4288..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/server-form.js +++ /dev/null @@ -1,85 +0,0 @@ -import React from "react"; -import * as _ from "lodash"; -const cx = require('classnames'); - -export default class ServerForm extends React.Component { - - constructor(props) { - super(props) - - this.onInputValueChanged = this.onInputValueChanged.bind(this) - } - - onInputValueChanged(e) { - let target = e.target - let field = target.getAttribute('name'); - let value = target.value; - if (target.type === 'checkbox') { - value = target.checked - } - this.props - .onValueChange(field, value) - } - - render() { - var errors = this.props.errors; - var hasErorrs = typeof errors !== 'undefined' && errors && errors.length > 0; - var classes = cx({ - 'btn': true, - 'btn-default': true, - 'disabled': !this.props.dirty, - 'btn-success': this.props.saved && !hasErorrs, - 'btn-warning': hasErorrs, - 'shake': hasErorrs, - 'freez': hasErorrs, - 'shake-rotate': hasErorrs - }); - var hostnameClasses = cx('form-group', { - 'has-error': _.find(errors, (error)=> { - return error.field === 'hostname' - }) !== undefined - }) - return ( -
-
- - -
- -
-
-
- - -
- -
-
-
-
-
- -
-
-
-
-
- - - -
-
-
- ); - } - -} diff --git a/grails-app/assets/javascripts/app/components/monitorings/service-checks-list.js b/grails-app/assets/javascripts/app/components/monitorings/service-checks-list.js deleted file mode 100644 index b952dae..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/service-checks-list.js +++ /dev/null @@ -1,86 +0,0 @@ -import * as _ from "lodash"; -import FromNow from "../tools/from-now"; -import FormatedDate from "../tools/formated-date"; -import React from "react"; -import BaseComponent from "../tools/base-component"; -import ReactPaginate from "react-paginate"; -const cx = require('classnames'); -const rd3 = require('react-d3'); -const LineChart = rd3.LineChart; - -export default class ServiceChecksList extends BaseComponent { - - constructor(props) { - super(props) - - this.state = { - checks: [], - total: 1 - } - - this.loadObjectsFromServer() - } - - loadObjectsFromServer() { - if (this.props.monitoring.id) { - let max = this.getMax(); - let offset = this.getOffset(); - this.getMonitoringService().checks(this.props.monitoring, {max, offset}).then(json=> { - this.setState(_.assign(this.state, { - checks: json.checks, - total: json.total - })); - }); - } - } - - render() { - /*let chartData = _.map(this.state.checks, (check)=>{ - return {label: check.dateCreated, value: check.responseTime}; - }); - return ()*/ - let offset = this.getOffset(); - let max = this.getMax(); - const {checks, total} = this.state - var rows = _.map(checks, (check)=> { - var rowClass = cx({'success': check.okay, 'danger': !check.okay}); - return ( - () - {check.responseCode} - {check.responseTime}ms - ) - }); - - - return ( -
-
- ...} - marginPagesDisplayed={5} - activeClassName="active" - containerClassName="pagination" - /> - - - - - - - - - {rows} -
TimeStatusCodeResponse Time
-
-
- ); - } - -} - -module.exports = ServiceChecksList; diff --git a/grails-app/assets/javascripts/app/components/monitorings/service-form.js b/grails-app/assets/javascripts/app/components/monitorings/service-form.js deleted file mode 100644 index f8e2980..0000000 --- a/grails-app/assets/javascripts/app/components/monitorings/service-form.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; - -import React from "react"; -import SubmitButton from "../tools/submit-button"; -var cx = require('classnames'); - -export default class ServiceForm extends React.Component { - - onInputValueChanged(e) { - let target = e.target - let field = target.getAttribute('name'); - let value = target.value; - if (target.type === 'checkbox') { - value = target.checked - } - this.props.onValueChange(field, value) - } - - render() { - var errors = this.props.errors; - var hasErorrs = typeof errors !== 'undefined' && errors && errors.length > 0; - var classes = cx({ - 'disabled': !this.props.dirty, - 'btn-success': this.props.saved && !hasErorrs, - 'btn-danger': this.props.saved && hasErorrs, - 'shake': this.props.saved && hasErorrs, - 'freez': this.props.saved && hasErorrs, - 'shake-rotate': this.props.saved && hasErorrs - }); - return ( -
-
- - -
- -
-
-
- -
- -
-
-
-
-
- -
-
-
-
-
- -   - -
-
-
- ); - } - -} diff --git a/grails-app/assets/javascripts/app/components/navbar/item.js b/grails-app/assets/javascripts/app/components/navbar/item.js index c3de445..54f9cd1 100644 --- a/grails-app/assets/javascripts/app/components/navbar/item.js +++ b/grails-app/assets/javascripts/app/components/navbar/item.js @@ -17,14 +17,18 @@ export default class NavbarItem extends BaseComponent { } render() { + const {danger, currentAction, action, roleNeeded, icon, text} = this.props; var classes = cx({ - 'danger': this.props.danger === true, - 'active': this.props.currentAction == this.props.action && this.props.danger !== true + 'danger': danger === true, + 'active': currentAction == action && danger !== true }); - var iconClass = 'fa fa-' + this.props.icon; + var iconClass = 'fa fa-' + icon; var shouldRender = false; - if (this.props.roleNeeded) { - if (this.iHaveRole(this.props.roleNeeded)) { + if (roleNeeded) { + let role = roleNeeded; + if (!Array.isArray(role)) + role = [role]; + if (this.iHaveAnyRole(role)) { shouldRender = true } } else { @@ -34,7 +38,7 @@ export default class NavbarItem extends BaseComponent { return (
  • - {this.props.text} + {text}
  • ) diff --git a/grails-app/assets/javascripts/app/components/navbar/sidebar.js b/grails-app/assets/javascripts/app/components/navbar/sidebar.js index ebedd6c..c7a8011 100644 --- a/grails-app/assets/javascripts/app/components/navbar/sidebar.js +++ b/grails-app/assets/javascripts/app/components/navbar/sidebar.js @@ -1,7 +1,5 @@ var cx = require('classnames'); -let MonitoringService = require('../../services/monitoring-service.js'); let ApplicationService = require('../../services/application-service.js'); -let MonitoringEvents = require('../../events/monitoring-events.js'); let AppEvents = require('../../events/application-events.js'); import React from "react"; import WithRole from "../tools/with-role"; @@ -20,7 +18,6 @@ export default class Sidebar extends BaseComponent { this._interval = -1; this.state = { expanded: false, - monitoringAlerts: false } } @@ -29,24 +26,16 @@ export default class Sidebar extends BaseComponent { if ((stats.YELLOW !== undefined && stats.YELLOW > 0) || (stats.RED !== undefined && stats.RED > 0)) { result = true } - this.state.monitoringAlerts = result; this.setState(this.state) } - _selectedAppChanged() { - MonitoringService.stats(ApplicationService.getSelected()) - } - componentDidMount() { // this._interval = setInterval(()=>{ - // MonitoringService.stats(ApplicationService.getSelected()) // }, 5000) - this.getEmitter().on(MonitoringEvents.MONITORING_STATS_UPDATED, this._onStatsDidUpdate) this.getEmitter().on(AppEvents.SELECTED_APP_CHANGED, this._selectedAppChanged) } componentWillUnmount() { - this.getEmitter().removeListener(MonitoringEvents.MONITORING_STATS_UPDATED, this._onStatsDidUpdate) this.getEmitter().removeListener(AppEvents.SELECTED_APP_CHANGED, this._selectedAppChanged) clearInterval(this._interval) } @@ -76,9 +65,8 @@ export default class Sidebar extends BaseComponent {
      - {/**/} - +
      diff --git a/grails-app/assets/javascripts/app/components/tools/base-component.js b/grails-app/assets/javascripts/app/components/tools/base-component.js index 9e61649..faa6872 100644 --- a/grails-app/assets/javascripts/app/components/tools/base-component.js +++ b/grails-app/assets/javascripts/app/components/tools/base-component.js @@ -142,10 +142,6 @@ export default class BaseComponent extends React.Component { return this.getApp().deploymentService } - getMonitoringService() { - return this.getApp().monitoringService - } - getSettingsService() { return this.getApp().settingsService } diff --git a/grails-app/assets/javascripts/app/components/tools/with-role.js b/grails-app/assets/javascripts/app/components/tools/with-role.js index 060a9d7..99990bf 100644 --- a/grails-app/assets/javascripts/app/components/tools/with-role.js +++ b/grails-app/assets/javascripts/app/components/tools/with-role.js @@ -1,5 +1,6 @@ import React from "react"; import * as _ from "lodash"; +import Hero from "./hero"; export default class WithRole extends React.Component { @@ -15,6 +16,6 @@ export default class WithRole extends React.Component { let user = this.props.user; let role = this.props.role; let roles = role ? [role] : this.props.roles; - return this.userHasAnyRole(user, roles) ? this.props.children :
      ; + return this.userHasAnyRole(user, roles) ? this.props.children : (this.props.notAllowed ||
      ); } } diff --git a/grails-app/assets/javascripts/app/components/users/user-list.js b/grails-app/assets/javascripts/app/components/users/user-list.js index 937a867..47a473c 100644 --- a/grails-app/assets/javascripts/app/components/users/user-list.js +++ b/grails-app/assets/javascripts/app/components/users/user-list.js @@ -4,7 +4,10 @@ import React from "react"; import BaseComponent from "../tools/base-component.js"; import LoadingHero from "../tools/loading-hero"; import UserListRow from "./user-list-row"; +import WithRole from "../tools/with-role"; +import Hero from "../tools/hero"; +const ROLES_NEEDED = ['ROLE_ROOT', 'ROLE_ADMIN']; export default class UserList extends BaseComponent { constructor(props) { @@ -16,15 +19,13 @@ export default class UserList extends BaseComponent { } getUserList() { - if (this.iHaveAnyRole(['ROLE_ADMIN', 'ROLE_ROOT'])) { - this.getUserService().list(50, 0) - .then((response) => { - this.setState({users: response.users}) - }) - .catch((err) => { - throw(err) - }) - } + this.getUserService().list(50, 0) + .then((response) => { + this.setState({users: response.users}) + }) + .catch((err) => { + throw(err) + }) } render() { @@ -36,24 +37,26 @@ export default class UserList extends BaseComponent { rows.push(); }); return ( -
      - - - - - - - - - - - {rows} -
      NameUsernameemailenabled - -
      -
      +

      You are not allowed to do this!

      }> +
      + + + + + + + + + + + {rows} +
      NameUsernameemailenabled + +
      +
      +
      ); } diff --git a/grails-app/assets/javascripts/app/events/monitoring-events.js b/grails-app/assets/javascripts/app/events/monitoring-events.js deleted file mode 100644 index af9f78a..0000000 --- a/grails-app/assets/javascripts/app/events/monitoring-events.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -var keyMirror = require('keymirror'); - -var MonitoringEvents = keyMirror({ - MONITORING_DELETED: null, - MONITORING_UPDATED: null, - MONITORING_CREATED: null, - MONITORING_SAVE_FAILED: null, - MONITORING_STATS_UPDATED: null -}); - -module.exports = MonitoringEvents; diff --git a/grails-app/assets/javascripts/app/services/monitoring-service.js b/grails-app/assets/javascripts/app/services/monitoring-service.js deleted file mode 100644 index 27f6a6c..0000000 --- a/grails-app/assets/javascripts/app/services/monitoring-service.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -import BaseService from "./base-service"; -const PATH = '/api/app/monitorings/'; - -export default class MonitoringService extends BaseService { - - buildPath(id) { - return `${this.baseUrl}${PATH}${id || ''}` - } - - get(id) { - return this.doGet(this.buildPath(id)) - } - - list(listParams) { - let params = { - sort: 'name', - order: 'asc' - }; - params.offset = listParams.offset || 0; - params.max = listParams.max || 20; - params.showDisabled = listParams.showDisabled || false; - if (listParams.type) - params.type = listParams.type; - if (listParams.status) - params.status = listParams.status; - - return this.doGet(this.buildPath(), params) - } - - stats() { - return this.doGet(`${this.buildPath()}/checks`); - } - - checks(monitoring, listParams) { - let params = { - sort: 'dateCreated', - order: 'desc' - }; - params.offset = listParams.offset || 0; - params.max = listParams.max || 20; - return this.doGet(`${this.buildPath(monitoring.id)}/checks`); - } - - save(monitoring) { - this.doPostPut(this.buildPath(), monitoring) - } - - del(monitoring) { - return this.doDel(this.buildPath(monitoring.id)); - } -} diff --git a/grails-app/assets/javascripts/app/services/user-service.js b/grails-app/assets/javascripts/app/services/user-service.js index 0b52dda..0042ae7 100644 --- a/grails-app/assets/javascripts/app/services/user-service.js +++ b/grails-app/assets/javascripts/app/services/user-service.js @@ -60,32 +60,15 @@ export default class UserService extends BaseService { } save(user) { - let headers = this.getHeaders(); - headers.set('Content-Type', 'application/json'); - return fetch(`${this.baseUrl}${PATH}${user.id || ''}`, { - headers: headers, - method: user.id ? 'PUT' : 'POST', - body: JSON.stringify(user) - }).then((resp) => { - if (resp.status === 200) { - return resp.json() - } else { - throw resp - } - }) + return this.doPostPut(`${this.baseUrl}${PATH}`, user); } del(user) { - return fetch(this.getRequest(`${this.baseUrl}${PATH}${user.id}`, 'DELETE')) - .then((resp) => { - return resp.json(); - }); + return this.doDel(`${this.baseUrl}${PATH}${user.id}`) } list(max, offset) { - return fetch(this.getRequest(`${this.baseUrl}${PATH}`)).then((resp) => { - return resp.json() - }) + return this.doGet(`${this.baseUrl}${PATH}`, {max, offset}) } _loggedIn(user) { diff --git a/grails-app/assets/stylesheets/app/components/_monitoring-list.scss b/grails-app/assets/stylesheets/app/components/_monitoring-list.scss deleted file mode 100644 index 34554a2..0000000 --- a/grails-app/assets/stylesheets/app/components/_monitoring-list.scss +++ /dev/null @@ -1,118 +0,0 @@ -@import "../variables"; - -.monitorings-list { - display: flex; - // flex-wrap: wrap; - flex-direction: column; - justify-content: flex-end; - align-content: space-around; - .list-row { - span.feature-icon { - float: left; - margin-top: 15px; - margin-right: 5px; - } - border-left: 5px solid #aaa; - &.red { - border-left-color: darken($state-danger-border, 25%); - } - &.none { - border-left-color: darken($state-info-border, 25%); - } - &.yellow { - border-left-color: darken($state-warning-border, 25%); - } - &.green { - border-left-color: darken($state-success-border, 25%); - } - &.disabled { - color: #888 !important; - background-color: #ccc; - border-left: none; - } - display: flex; - justify-content: space-around; - align-items: stretch; - margin: 3px; - padding: 5px; - .info { - flex-grow: 3; - flex-basis: 0; - } - .url-check { - flex-grow: 3; - flex-basis: 0; - display: flex; - justify-content: flex-end; - div { - padding: 5px; - border-radius: 3px; - border: 1px solid; - border-color: transparent; - display: flex; - align-items: center; - justify-content: center; - span { - margin-right: 3px; - &:last-child { - margin: 0; - } - } - &.green { - background-color: $state-success-bg; - color: $state-success-text; - border-color: $state-success-border; - } - &.yellow { - background-color: $state-warning-bg; - color: $state-warning-text; - border-color: $state-warning-border; - } - &.red { - background-color: $state-danger-bg; - color: $state-danger-text; - border-color: $state-danger-border; - } - - } - } - .ping-times { - font-size: 13pt; - flex-grow: 1; - flex-basis: 0; - display: flex; - justify-content: flex-end; - div { - margin: 0 2px; - display: flex; - align-items: center; - justify-content: center; - flex-grow: 1; - max-width: 100px; - border: 1px solid; - border-radius: 3px; - border-color: transparent; - &.green { - background-color: $state-success-bg; - color: $state-success-text; - border-color: $state-success-border; - } - &.yellow { - background-color: $state-warning-bg; - color: $state-warning-text; - border-color: $state-warning-border; - } - &.red { - background-color: $state-danger-bg; - color: $state-danger-text; - border-color: $state-danger-border; - } - &.none { - background-color: $state-info-bg; - color: $state-info-text; - border-color: $state-info-border; - } - } - } - } -} diff --git a/grails-app/assets/stylesheets/app/main.scss b/grails-app/assets/stylesheets/app/main.scss index 43def0e..d94d45d 100644 --- a/grails-app/assets/stylesheets/app/main.scss +++ b/grails-app/assets/stylesheets/app/main.scss @@ -7,7 +7,6 @@ $fa-font-path: "~font-awesome/fonts"; @import "./components/sidebar"; @import "./components/list-row"; @import "./components/entry-details"; -@import "./components/monitoring-list"; @import "./components/pagination"; @import "./components/entry-list"; @import "./components/settings"; diff --git a/grails-app/controllers/errbuddy/MonitoringController.groovy b/grails-app/controllers/errbuddy/MonitoringController.groovy deleted file mode 100644 index 2ba8111..0000000 --- a/grails-app/controllers/errbuddy/MonitoringController.groovy +++ /dev/null @@ -1,110 +0,0 @@ -package errbuddy - -import org.springframework.http.HttpStatus - -class MonitoringController extends AbstractApiController { - - static allowedMethods = [list: 'GET', servers: 'GET', get: 'GET', update: 'PUT', create: 'POST', delete: 'DELETE', checks: 'GET', stats: 'GET'] - - def monitoringService - - def create() { - def monitoring = monitoringService.create(request.JSON as Map) - if (monitoring.validate()) - renderJson([monitoring: monitoring]) - else { - response.status = HttpStatus.BAD_REQUEST.value() - renderJson([errors: monitoring.errors.allErrors]) - } - if (monitoring.enabled) { - jesqueService.enqueue("generic", MonitoringCheckJob, monitoring.id) - } - } - - def get() { - withMonitoring { Monitoring monitoring -> - renderJson([monitoring: monitoring]) - } - } - - def checks() { - withMonitoring { Monitoring monitoring -> - sanitizeParams() - def list = MonitoringCheck.findAllByMonitoring(monitoring, params) - def total = MonitoringCheck.countByMonitoring(monitoring, params) - renderJson(checks: list, total: total) - } - } - - def list() { - Monitoring.Type type - if (params.get("type")) { - try { - type = Monitoring.Type.valueOf(params.get("type").toString()) - } catch (Exception e) { - response.status = HttpStatus.BAD_REQUEST.value() - renderJson([type: 'invalid']) - return - } - } - def monitorings = Monitoring.createCriteria().list(params) { - if (!params.getBoolean('showDisabled', false)) { - eq('enabled', true) - } - if (type) { - eq('type', type) - } - if (params.status && params.status in ['green', 'yellow', 'red']) { - // we only allow red and green as status values - eq('status', Monitoring.Status.valueOf(params.status.toString().toUpperCase())) - } - } - renderJson([total: monitorings.totalCount, monitorings: monitorings, unfilteredTotal: Monitoring.count]) - } - - def update() { - withMonitoring { Monitoring monitoring -> - monitoringService.update(request.JSON as Map, monitoring) - if (monitoring.validate()) - renderJson([monitoring: monitoring]) - else { - response.status = HttpStatus.BAD_REQUEST.value() - renderJson([errors: monitoring.errors.allErrors]) - } - if (monitoring.enabled) { - jesqueService.enqueue("generic", MonitoringCheckJob, monitoring.id) - } - } - } - - def delete() { - withMonitoring { Monitoring monitoring -> - def deleted = monitoringService.delete(monitoring) - renderJson([success: deleted]) - } - } - - def stats() { - def stats = [:] - Monitoring.createCriteria().list { - eq('enabled', true) - projections { - countDistinct('status') - } - groupProperty('status') - }.each { - stats[it[1]] = it[0] - } - - renderJson([stats: stats]) - } - - private withMonitoring(Closure callable) { - Monitoring monitoring = Monitoring.get(params.getLong('id')) - if (!monitoring) { - response.status = HttpStatus.NOT_FOUND.value() - } else { - callable.call monitoring - } - } -} diff --git a/grails-app/controllers/errbuddy/ShortlinkController.groovy b/grails-app/controllers/errbuddy/ShortlinkController.groovy index 061cb71..3cfc406 100644 --- a/grails-app/controllers/errbuddy/ShortlinkController.groovy +++ b/grails-app/controllers/errbuddy/ShortlinkController.groovy @@ -1,13 +1,8 @@ package errbuddy -import grails.plugins.redis.RedisService - class ShortlinkController { - RedisService redisService - def redirect(String identifier) { - Entry entry = Entry.findByIdentifier(identifier) if (entry) { diff --git a/grails-app/controllers/errbuddy/UrlMappings.groovy b/grails-app/controllers/errbuddy/UrlMappings.groovy index acff059..6eea057 100644 --- a/grails-app/controllers/errbuddy/UrlMappings.groovy +++ b/grails-app/controllers/errbuddy/UrlMappings.groovy @@ -12,12 +12,6 @@ class UrlMappings { "/api/app/users/$id/roles"(controller: 'user', action: 'roles') "/api/app/users"(controller: 'user', action: [POST: 'create', GET: 'list']) - "/api/app/monitorings"(controller: 'monitoring', action: [POST: 'create', GET: 'list']) - "/api/app/monitorings/$id"(controller: 'monitoring', action: [GET: 'get', PUT: 'update', DELETE: 'delete']) - "/api/app/monitorings/$id/checks"(controller: 'monitoring', action: [GET: 'checks']) - - "/api/app/monitorings/stats"(controller: 'monitoring', action: 'stats') - "/api/app/entries/$id/$entry"(controller: 'entryGroup', action: [GET: 'get', DELETE: 'delete']) "/api/app/entries/$id"(controller: 'entryGroup', action: [DELETE: 'delete']) diff --git a/grails-app/domain/errbuddy/App.groovy b/grails-app/domain/errbuddy/App.groovy index 668b879..24462eb 100644 --- a/grails-app/domain/errbuddy/App.groovy +++ b/grails-app/domain/errbuddy/App.groovy @@ -6,7 +6,7 @@ import org.joda.time.DateTime class App implements HasJsonBody { static searchable = { - except = ['filters', 'entryGroups', 'userAlertSettings', 'deployments', 'monitorings'] + except = ['filters', 'entryGroups', 'userAlertSettings', 'deployments'] root false } @@ -20,7 +20,7 @@ class App implements HasJsonBody { deployments sort: 'dateCreated', order: 'DESC' } - static hasMany = [entryGroups: EntryGroup, filters: Filter, deployments: Deployment, monitorings: Monitoring] + static hasMany = [entryGroups: EntryGroup, filters: Filter, deployments: Deployment] String name String apiKey diff --git a/grails-app/domain/errbuddy/Monitoring.groovy b/grails-app/domain/errbuddy/Monitoring.groovy deleted file mode 100644 index bc42f74..0000000 --- a/grails-app/domain/errbuddy/Monitoring.groovy +++ /dev/null @@ -1,67 +0,0 @@ -package errbuddy - -import org.joda.time.DateTime - -class Monitoring implements HasJsonBody { - - String hostname - String url - String name - - int averageResponseTime - - boolean enabled - Status status - - DateTime dateCreated - DateTime lastUpdated - DateTime lastChecked - DateTime lastSuccess - - Type type - - MonitoringCheck latestCheck - - static hasMany = [checks: MonitoringCheck] - - @Override - Map getJsonBody() { - [ - id : id, - name : name, - hostname : hostname, - url : url, - enabled : enabled, - type : type?.name(), - status : status ? status.name() : Status.BLUE.name(), - averageResponseTime: averageResponseTime, - lastChecked : lastChecked?.millis, - lastSuccess : lastSuccess?.millis - ] - } - - public static enum Type { - SERVER, - SERVICE - } - - public static enum Status { - BLUE, // no checks have ever been performed - GREEN, // none of the last 20 checks have failed - YELLOW, // at least one, but not the latest check failed - RED // at least the latest check failed - } - - static constraints = { - hostname unique: true, nullable: true - url unique: true, nullable: true - lastChecked nullable: true - lastSuccess nullable: true - latestCheck nullable: true - status nullable: true - } - - public getLatestChecks() { - MonitoringCheck.findAllByMonitoring(this, [max: 20, sort: 'dateCreated', order: 'desc']) - } -} diff --git a/grails-app/domain/errbuddy/MonitoringCheck.groovy b/grails-app/domain/errbuddy/MonitoringCheck.groovy deleted file mode 100644 index 6ff4319..0000000 --- a/grails-app/domain/errbuddy/MonitoringCheck.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package errbuddy - -import org.joda.time.DateTime - -class MonitoringCheck implements HasJsonBody { - - int responseTime - int responseCode - boolean okay - - DateTime dateCreated - - static belongsTo = [monitoring: Monitoring] - - @Override - Map getJsonBody() { - [ - id : id, - responseTime: responseTime, - responseCode: responseCode, - okay : okay, - dateCreated : dateCreated.millis - ] - } -} diff --git a/grails-app/jobs/errbuddy/ApplicationDeleteJob.groovy b/grails-app/jobs/errbuddy/ApplicationDeleteJob.groovy index d142b5a..b809174 100644 --- a/grails-app/jobs/errbuddy/ApplicationDeleteJob.groovy +++ b/grails-app/jobs/errbuddy/ApplicationDeleteJob.groovy @@ -2,6 +2,8 @@ package errbuddy class ApplicationDeleteJob { + static queueName = "put" + def applicationService def perform(Serializable id) { diff --git a/grails-app/jobs/errbuddy/ApplicationDeploymentJob.groovy b/grails-app/jobs/errbuddy/ApplicationDeploymentJob.groovy index 09edc3b..f333ab8 100644 --- a/grails-app/jobs/errbuddy/ApplicationDeploymentJob.groovy +++ b/grails-app/jobs/errbuddy/ApplicationDeploymentJob.groovy @@ -2,6 +2,8 @@ package errbuddy class ApplicationDeploymentJob { + static queueName = "generic" + def applicationService def perform(def appId, def version, def hostname) { diff --git a/grails-app/jobs/errbuddy/DataRetentionJob.groovy b/grails-app/jobs/errbuddy/DataRetentionJob.groovy index d5c1c48..89c7e52 100644 --- a/grails-app/jobs/errbuddy/DataRetentionJob.groovy +++ b/grails-app/jobs/errbuddy/DataRetentionJob.groovy @@ -2,12 +2,14 @@ package errbuddy class DataRetentionJob { + static queueName = "put" + static triggers = { cron name: 'DataRetentionJob', jesqueJobName: DataRetentionJob.simpleName, - jesqueQueue: "put", + jesqueQueue: queueName, cronExpression: "0 */5 * * * ?", - args: [] + args: [0] } def dataRetentionService diff --git a/grails-app/jobs/errbuddy/DeleteEmptyGroupsJob.groovy b/grails-app/jobs/errbuddy/DeleteEmptyGroupsJob.groovy index ce07b0d..0f42cf0 100644 --- a/grails-app/jobs/errbuddy/DeleteEmptyGroupsJob.groovy +++ b/grails-app/jobs/errbuddy/DeleteEmptyGroupsJob.groovy @@ -2,11 +2,13 @@ package errbuddy class DeleteEmptyGroupsJob { + static queueName = "generic" + static triggers = { // 10 minutes after every hour cron name: 'DeleteEmptyGroupsJob', jesqueJobName: DeleteEmptyGroupsJob.simpleName, - jesqueQueue: "generic", + jesqueQueue: queueName, cronExpression: "0 10 * ? * * *", args: [] } diff --git a/grails-app/jobs/errbuddy/DeleteEntryGroupJob.groovy b/grails-app/jobs/errbuddy/DeleteEntryGroupJob.groovy index 240e82a..98e250b 100644 --- a/grails-app/jobs/errbuddy/DeleteEntryGroupJob.groovy +++ b/grails-app/jobs/errbuddy/DeleteEntryGroupJob.groovy @@ -2,6 +2,8 @@ package errbuddy class DeleteEntryGroupJob { + static queueName = "generic" + def entryGroupService def perform(Serializable id, boolean deleteEntries) { diff --git a/grails-app/jobs/errbuddy/EntryDeleteJob.groovy b/grails-app/jobs/errbuddy/EntryDeleteJob.groovy index 182b6f8..f18a3d7 100644 --- a/grails-app/jobs/errbuddy/EntryDeleteJob.groovy +++ b/grails-app/jobs/errbuddy/EntryDeleteJob.groovy @@ -2,6 +2,8 @@ package errbuddy class EntryDeleteJob { + static queueName = "put" + def entryService def perform(Serializable id, boolean doCheckLatest = true) { diff --git a/grails-app/jobs/errbuddy/EntryPutJob.groovy b/grails-app/jobs/errbuddy/EntryPutJob.groovy index b470fb6..373187b 100644 --- a/grails-app/jobs/errbuddy/EntryPutJob.groovy +++ b/grails-app/jobs/errbuddy/EntryPutJob.groovy @@ -2,6 +2,8 @@ package errbuddy class EntryPutJob { + static queueName = "put" + def entryService def perform(Serializable applicationId, String data) { diff --git a/grails-app/jobs/errbuddy/FindSimilarEntriesJob.groovy b/grails-app/jobs/errbuddy/FindSimilarEntriesJob.groovy index c0bf333..e5d9389 100644 --- a/grails-app/jobs/errbuddy/FindSimilarEntriesJob.groovy +++ b/grails-app/jobs/errbuddy/FindSimilarEntriesJob.groovy @@ -2,6 +2,8 @@ package errbuddy class FindSimilarEntriesJob { + static queueName = "generic" + def entryService def perform(Serializable id) { diff --git a/grails-app/jobs/errbuddy/MonitoringCheckCreatorJob.groovy b/grails-app/jobs/errbuddy/MonitoringCheckCreatorJob.groovy deleted file mode 100644 index 2301ff2..0000000 --- a/grails-app/jobs/errbuddy/MonitoringCheckCreatorJob.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package errbuddy - -import org.joda.time.DateTime - -class MonitoringCheckCreatorJob { - -// static triggers = { -// // every minute -// cron name: 'MonitoringCheckCreatorJob', -// jesqueJobName: MonitoringCheckCreatorJob.simpleName, -// jesqueQueue: "generic", -// cronExpression: "0 * * ? * * *", -// args: [] -// } - - def jesqueService - - def perform() { - Monitoring.findAllByEnabled(true).eachWithIndex { Monitoring monitoring, i -> - log.info "enqueuing check job for $monitoring.id" - jesqueService.enqueueAt(DateTime.now().plusSeconds(i), QueueConfiguration.getQueueName(MonitoringCheckJob), MonitoringCheckJob, [monitoring.id]) - } - } -} diff --git a/grails-app/jobs/errbuddy/MonitoringCheckJob.groovy b/grails-app/jobs/errbuddy/MonitoringCheckJob.groovy deleted file mode 100644 index 2c8ebab..0000000 --- a/grails-app/jobs/errbuddy/MonitoringCheckJob.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package errbuddy - -class MonitoringCheckJob { - - def monitoringCheckService - - def perform(long id) { - Monitoring monitoring = Monitoring.get(id) - monitoringCheckService.check(monitoring) - } -} diff --git a/grails-app/jobs/errbuddy/PutIntoEntryGroupJob.groovy b/grails-app/jobs/errbuddy/PutIntoEntryGroupJob.groovy index 575d03b..192f00e 100644 --- a/grails-app/jobs/errbuddy/PutIntoEntryGroupJob.groovy +++ b/grails-app/jobs/errbuddy/PutIntoEntryGroupJob.groovy @@ -2,6 +2,8 @@ package errbuddy class PutIntoEntryGroupJob { + static queueName = "addToGroupQueue" + def entryService def perform(entryGroupid, entryid) { diff --git a/grails-app/jobs/errbuddy/RefindFromCollectorJob.groovy b/grails-app/jobs/errbuddy/RefindFromCollectorJob.groovy index e660c28..81a7437 100644 --- a/grails-app/jobs/errbuddy/RefindFromCollectorJob.groovy +++ b/grails-app/jobs/errbuddy/RefindFromCollectorJob.groovy @@ -2,11 +2,13 @@ package errbuddy class RefindFromCollectorJob { + static queueName = "generic" + static triggers = { // every 2 hours cron name: 'RefindFromCollectorJob', jesqueJobName: RefindFromCollectorJob.simpleName, - jesqueQueue: "generic", + jesqueQueue: queueName, cronExpression: "0 * * ? * * *", args: [] } diff --git a/grails-app/jobs/errbuddy/ReindexJob.groovy b/grails-app/jobs/errbuddy/ReindexJob.groovy index 4cf5328..33f654a 100644 --- a/grails-app/jobs/errbuddy/ReindexJob.groovy +++ b/grails-app/jobs/errbuddy/ReindexJob.groovy @@ -2,6 +2,8 @@ package errbuddy class ReindexJob { + static queueName = "generic" + def elasticSearchService def elasticSearchAdminService diff --git a/grails-app/migrations/20170203_add_identifier_index.groovy b/grails-app/migrations/20170203_add_identifier_index.groovy new file mode 100644 index 0000000..250dbfb --- /dev/null +++ b/grails-app/migrations/20170203_add_identifier_index.groovy @@ -0,0 +1,8 @@ +databaseChangeLog = { + + changeSet(author: "philipp", id: "20170216") { + createIndex(tableName: "entry", indexName: "identifier_idx") { + column(name: "identifier") + } + } +} diff --git a/grails-app/migrations/20172503_drop_monitoring.groovy b/grails-app/migrations/20172503_drop_monitoring.groovy new file mode 100644 index 0000000..ccda09a --- /dev/null +++ b/grails-app/migrations/20172503_drop_monitoring.groovy @@ -0,0 +1,21 @@ +databaseChangeLog = { + + changeSet(author: "philipp", id: "20172503-1", comment: 'drop FK constraints') { + dropAllForeignKeyConstraints(baseTableName: "monitoring") + dropAllForeignKeyConstraints(baseTableName: "monitoring_check") + dropIndex(tableName: 'monitoring', indexName: 'FK_cp7it2rk9ohbnykrq0hnqd2ei') + } + + changeSet(author: "philipp", id: "20172503-2", comment: 'drop monitoring check table') { + dropTable(tableName: 'monitoring_check') + } + + changeSet(author: "philipp", id: "20172503-3", comment: 'drop application monitoring mapping table') { + dropTable(tableName: 'application_monitoring') + } + + changeSet(author: "philipp", id: "20172503-4", comment: 'drop monitoring table') { + dropTable(tableName: 'monitoring') + } + +} diff --git a/grails-app/migrations/changelog.groovy b/grails-app/migrations/changelog.groovy index 84d0056..f955edf 100644 --- a/grails-app/migrations/changelog.groovy +++ b/grails-app/migrations/changelog.groovy @@ -2,4 +2,5 @@ databaseChangeLog = { include file: '20160912_initial.groovy' include file: '20171602_rename_newest.groovy' + include file: '20172503_drop_monitoring.groovy' } diff --git a/grails-app/services/errbuddy/EntryService.groovy b/grails-app/services/errbuddy/EntryService.groovy index 25a488d..c4105a4 100644 --- a/grails-app/services/errbuddy/EntryService.groovy +++ b/grails-app/services/errbuddy/EntryService.groovy @@ -88,7 +88,7 @@ class EntryService { entry.refindSimilar = false entry.save(flush: true) - jesqueService.enqueue("add_to_group", PutIntoEntryGroupJob, [entryGroup.id, entry.id]) + jesqueService.enqueue(PutIntoEntryGroupJob.queueName, PutIntoEntryGroupJob, [entryGroup.id, entry.id]) } void addToEntryGroup(long entryGroupId, long entryId) { diff --git a/grails-app/services/errbuddy/MonitoringCheckService.groovy b/grails-app/services/errbuddy/MonitoringCheckService.groovy deleted file mode 100644 index 529d2c7..0000000 --- a/grails-app/services/errbuddy/MonitoringCheckService.groovy +++ /dev/null @@ -1,93 +0,0 @@ -package errbuddy - -import grails.transaction.Transactional -import org.joda.time.DateTime - -@Transactional -class MonitoringCheckService { - - private static final int MAX_WAIT_TIME = 10000 - def grailsApplication - - def check(Monitoring monitoring) { - long start = System.currentTimeMillis() - def okay = doPing(monitoring.hostname, 1) - long done = System.currentTimeMillis() - MonitoringCheck monitoringCheck = new MonitoringCheck(monitoring: monitoring) - updateMonitoringCheckResult(monitoringCheck, [success: okay, time: done - start]) - updateMonitoringStatus(monitoring, monitoringCheck, DateTime.now()) - if (monitoringCheck.validate()) { - monitoringCheck.save() - monitoring.save() - } else { - log.error("MontoringCheck could not be validated: $monitoringCheck.errors.allErrors") - } - } - - /** - * F*** windows, we go for unix-like ping only... - * @param host - * @param timeout - * @return - */ - boolean doPing(host, timeout) { - def processString = "ping -c 1 -t $timeout $host" - def result = processString.execute().waitFor() - result == 0 - } - - def updateMonitoringCheckResult(MonitoringCheck monitoringCheck, Map resultJson) { - switch (monitoringCheck.monitoring.type) { - case Monitoring.Type.SERVER: - monitoringCheck.okay = resultJson.success - monitoringCheck.responseTime = resultJson.time - break - case Monitoring.Type.SERVICE: - monitoringCheck.responseCode = resultJson.statusCode - monitoringCheck.responseTime = resultJson.time - monitoringCheck.okay = resultJson.statusCode == 200 - break - } - } - - /** - * uses information of the given check result and updates the status of the given monitoring - * if check was not okay the status is being set to RED - * if check is green but one of the latest 20 checks failed, it is set to YELLOW - * if check is green and none of the last 20 checks failed, it is set to GREEN - * also lastSuccess and lastChecked is set and the given check is set as the latest - * @param monitoring - * @param monitoringCheck - * @param checkTime - * @return - */ - def updateMonitoringStatus(Monitoring monitoring, MonitoringCheck monitoringCheck, DateTime checkTime) { - if (!monitoringCheck.okay) { - monitoring.status = Monitoring.Status.RED - } else { - List latestChecks = MonitoringCheck.findAllByMonitoring(monitoring, [max: 20, sort: 'dateCreated', order: 'desc']) - monitoring.lastSuccess = checkTime - // find the last 20 - if (latestChecks.find { !it.okay }) { - monitoring.status = Monitoring.Status.YELLOW - } else { - monitoring.status = Monitoring.Status.GREEN - } - if (latestChecks) { - monitoring.averageResponseTime = latestChecks.sum { it.responseTime } / latestChecks.size() - } - } - - monitoring.lastChecked = checkTime - monitoring.latestCheck = monitoringCheck - } - - private String getServiceUrl(Monitoring monitoring) { - switch (monitoring.type) { - case Monitoring.Type.SERVER: return grailsApplication.config.application.services.ping.url - case Monitoring.Type.SERVICE: return grailsApplication.config.application.services.urlcheck.url - } - null - } - -} diff --git a/grails-app/services/errbuddy/MonitoringService.groovy b/grails-app/services/errbuddy/MonitoringService.groovy deleted file mode 100644 index 562fd72..0000000 --- a/grails-app/services/errbuddy/MonitoringService.groovy +++ /dev/null @@ -1,54 +0,0 @@ -package errbuddy - -import grails.transaction.Transactional - -@Transactional -class MonitoringService { - - private static final UPDATEABLE_PARAMS = ['name', 'enabled', 'hostname', 'url'] - - Monitoring create(Map params) { - Monitoring monitoring = new Monitoring() - bindParams(monitoring, params) - monitoring.type = Monitoring.Type.valueOf(params.type.toString()) - if (monitoring.validate()) { - monitoring.save() - } - monitoring - } - - Monitoring update(Map params, Monitoring monitoring) { - bindParams(monitoring, params) - if (monitoring.validate()) { - monitoring.save() - } - monitoring - } - - boolean delete(Monitoring toDelete) { - toDelete.enabled = false - toDelete.save(flush: true) // we have to disable all checks so we also have to flush here - clear(toDelete) - toDelete.delete() - } - - boolean clear(Monitoring monitoring) { - def count = MonitoringCheck.countByMonitoring(monitoring) - (0..count).step(1000) { offset -> - MonitoringCheck.findAllByMonitoring(monitoring, [max: 1000, offset: offset]).each { - it.delete() - } - } - } - - def bindParams(Monitoring monitoring, Map params) { - UPDATEABLE_PARAMS.each { param -> - def value = params[param] - if (value == 'null') - value = null - if (value != monitoring[param]) - monitoring[param] = value - } - } - -}