Grails Plugin exposing user-defined metrics (HeartBeat
) as strings, graphs or piecharts.
- Requires Grails 3.x
- Requires JQuery and ChartJS
- Auto-refresh
- Display HeartBeats as String, graphs, or piecharts
- HeartBeats with parameters
- CRUD for HeartBeats
- Live configuration test within the CRUD GUI ("Test" button)
- AJAX, GSP template, Controller, Service
- No security: you MUST control access yourself when invoking the HeartBeat (recommendation: add a SpringSecurity URL rule on
/heartBeat
) - No security: you MUST make sure the
script
invoked do no nasty things, like in groovySystem.exit()
(rejected) <g:heartBeat> TagLib
A CRUD interface is available at /heartbeat
:
Once you have created HeartBeats
, you can use them anywhere in your application, for example in an admin page:
The code used to insert HeartBeats
like in the previous picture:
<g:set var="list" value="${heartbeat.HeartBeat.list().sort { it.orderKey }}"/>
<g:set var="hideButtons" value="${params.boolean('hideButtons')}"/>
<g:set var="hideTitle" value="${params.boolean('hideTitle')}"/>
<g:set var="hideButtons" value="${params.boolean('hideButtons')}"/>
<div class="my_data_line">
<g:render
template="/heartBeat"
collection="${list.findAll { it.orderKey.startsWith 'A' }}"
/>
</div>
<div class="my_data_line">
<g:render
template="/heartBeat"
collection="${list.findAll { it.orderKey.startsWith 'B' }}"
/>
</div>
The <g:render template="/heartBeat"/>
template reads the following variables:
- REQUIRED
it
(of type HeartBeat) - OPTIONAL
hideButtons
if set totrue
, will hide the edit/delete buttons - OPTIONAL
hideData
if set totrue
, will not show theHeartBeat
data. It is hard to see why one would want to do this. - OPTIONAL
hideErrors
if set totrue
, errors while retrievingHeartBeat
data will not appear. - OPTIONAL
hideTitle
if set totrue
, will not show theHeartBeat
title
Within the HeartBeat
database table, the available fields are:
title
: the name of the metric, which will be shown in HTML as the title of the block.refreshRate
: how often to refresh the metric, in seconds. A typical value would be 60.type
: currently only sql or groovy. It names the language used to interpret the script field.display
: currently graph or text. In HTML, the former will show as a ChartJs canvas, while the later will show as a simple text.orderKey
: used to sort or filter the HeartBeats. You may want to useX-Y
matrix positioning, as in '5-3'.style
: a css set of properties, applied to the HTML div surronding the rendered HeartBeat, you may want to add coloring here, like"text-color:green;"
. // cssscript
: back-slash escaped code to execute to fetch the data, written in SQL or Groovy. Examples provided below.
When using HeartBeatParam
, theses are simply
name
: the name of the parameters, used in the EL script.value
: value that replaces the parameter.
Scripts may come with parameters, using Groovy's SimpleTemplateEngine.
-- Number of pets
select count(*) from Pet
-- Progession of number of pets on last 24h
SELECT
to_char(ts, 'YYYY-MM-DD HH24:mm'),
(select count(*) from pet where dateCreated < ts)
FROM
generate_series(now () - interval '1 day', now(), interval '1 hour') ts
-- number of pets by keeper
SELECT
keeper.name, count(*)
FROM
pets
inner join keeper USING keeper_id
// Number of pets
Pet.count()
// Number of pets older than parameter age
Pet.createCriteria().count { gt 'age', $age}
Within your own grails application:
- Add the dependency to the plugin, in
/build.gradle
dependencies {
compile "org.grails.plugins:heartbeat:2.1"
- Add the JavaScript code, in
/grails-app/assets/javascripts/application.js
//= require jquery-2.2.0.min
//= require chartjs.min
//= require heartbeat
- Show the
HeartBeats
, by inserting within an access-protected GSP
<g:set var="list" value="${heartbeat.HeartBeat.list().sort { it.orderKey }}"/>
<div class="my_data_line">
<g:render template="/heartBeat" collection="${list}" />
</div>
<g:link controller="heartBeat">HeartBeat Admin</g:link>
git clone https://github.com/igorrosenberg/grails-plugin-heartbeat.git
gradle bootRun
A webserver then is running.
- Add a new
HeartBeat
athttp://localhost:8080/heartBeat/create
- See it displayed at
http://localhost:8080/
If you want to contribute, here are some ideas:
- (very easy) in ‘_hearbeat.gsp‘, add a "fetch now" button, see issue #4
- (easy) make CRUD-dedicated JS only applicable to heartbeat CRUD pages (search for
$('.test.button').click
), see issue #5 - (easy) Bug: "Test" button does not show http 500 when it Occurs within the "show" view, see issue #6
- (easy) in ‘_heartbeat.gsp‘, add a clock, showing how long before the data gets updated, see issue #7
- (easy) remove useless files from the plugin code, like
grails-app/assets
, see issue #8 (easy) add pie-style charts, see issue #3DONE- (medium) remove jquery dependency, reverting to vanilla JavaScript, see issue #9
- (medium) Optimize JS, see issue #10
- (medium) Improve add param GUI (using default grails generate-view/controller feels clunky), see issue #11
- (hard) Make the js graph renderer configurable, so another chart library can be used, like D3
- (hard) auto-generate the doc: the README file is essentially copy-pasting the source code. It would be nice to simply dump the relevant code comments.
- (hard) caching results - is this possible without adding heavy dependencies, maintaining genericity and configurability? Is caching even desireable?