Merge pull request #520 from cachethq/metric-avg-sum

Allow metrics to calculate the sum or average. Closes #517.
This commit is contained in:
Joe Cohen
2015-03-17 14:54:31 -06:00
10 changed files with 71 additions and 26 deletions

View File

@@ -19,6 +19,7 @@ class CreateMetricsTable extends Migration
$table->string('suffix');
$table->text('description');
$table->decimal('default_value', 10, 3);
$table->tinyInteger('calc_type');
$table->boolean('display_chart')->default(1);
$table->timestamps();

View File

@@ -58,6 +58,9 @@ return [
'description' => 'Description',
'description-help' => 'You may also use Markdown.',
'display-chart' => 'Display chart on status page?',
'calc_type' => 'Calculation of metrics',
'type_sum' => 'Sum',
'type_avg' => 'Average',
'points' => [
'value' => 'Value',

View File

@@ -61,6 +61,9 @@ return [
'description-help' => 'You may also use Markdown.',
'display-chart' => 'Display chart on status page?',
'default-value' => 'Default value',
'calc_type' => 'Calculation of metrics',
'type_sum' => 'Sum',
'type_avg' => 'Average',
'points' => [
'value' => 'Value',

View File

@@ -59,6 +59,9 @@ return [
'description' => 'Descripción',
'description-help' => 'Puedes usar también Markdown.',
'display-chart' => '¿Vizualizar gráfica en la página de estado?',
'calc_type' => 'Calculation of metrics',
'type_sum' => 'Sum',
'type_avg' => 'Average',
'points' => [
'value' => 'Valor',

View File

@@ -58,6 +58,9 @@ return [
'description' => 'Description',
'description-help' => 'You may also use Markdown.',
'display-chart' => 'Display chart on status page?',
'calc_type' => 'Calculation of metrics',
'type_sum' => 'Sum',
'type_avg' => 'Average',
'points' => [
'value' => 'Value',

View File

@@ -61,6 +61,9 @@ return [
'description-help' => '',
'display-chart' => '',
'default-value' => '',
'calc_type' => 'Calculation of metrics',
'type_sum' => 'Sum',
'type_avg' => 'Average',
'points' => [
'value' => '',

View File

@@ -31,6 +31,13 @@
<textarea name="metric[description]" class="form-control" rows="5" required>{{ Input::old('metric.description') }}</textarea>
</div>
</div>
<div class="form-group">
<label>{{ trans('forms.metrics.calc_type') }}</label>
<select name="metric[calc_type]" class="form-control" required>
<option value="0" selected>{{ trans('forms.metrics.type_sum') }}</option>
<option value="1">{{ trans('forms.metrics.type_avg') }}</option>
</select>
</div>
<div class="form-group">
<label for="metric-default_value">{{ trans('forms.metrics.default-value') }}</label>
<input type="number" class="form-control" name="metric[default_value]" id="metric-default_value" value="{{ Input::old('metric.default_value') }}">

View File

@@ -31,6 +31,13 @@
<textarea name="metric[description]" class="form-control" rows="5" required>{{ $metric->description }}</textarea>
</div>
</div>
<div class="form-group">
<label>{{ trans('forms.metrics.calc_type') }}</label>
<select name="metric[calc_type]" class="form-control" required>
<option value="0" {{ $metric->calc_type === 0 ? "selected" : null }}>{{ trans('forms.metrics.type_sum') }}</option>
<option value="1" {{ $metric->calc_type === 1 ? "selected" : null }}>{{ trans('forms.metrics.type_avg') }}</option>
</select>
</div>
<div class="form-group">
<label for="metric-default_value">{{ trans('forms.metrics.default-value') }}</label>
<input type="number" class="form-control" name="metric[default_value]" id="metric-default_value" value="{{ $metric->default_value }}">

View File

@@ -31,37 +31,36 @@
</div>
</div>
<script>
var hourList = [];
var date = new Date();
(function () {
var hourList = [], date = new Date();
for (var i = 10; i >= 1; i--) {
hourList.push(moment(date).subtract(i, 'hours').seconds(0).format('HH:ss'));
}
for (var i = 10; i >= 1; i--) {
hourList.push(moment(date).subtract(i, 'hours').seconds(0).format('HH:ss'));
}
hourList.push(moment(date).seconds(0).format('HH:ss'));
hourList.push(moment(date).seconds(0).format('HH:ss'));
var data = {
showTooltips: false,
labels: hourList,
datasets: [{
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: [{{ implode(',', $points) }}]
}]
};
var data = {
showTooltips: false,
labels: hourList,
datasets: [{
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: [{{ implode(',', $points) }}]
}]
};
window.onload = function() {
var ctx = document.getElementById("metric-{{ $metric->id }}").getContext("2d");
window.myLine = new Chart(ctx).Line(data, {
new Chart(ctx).Line(data, {
scaleShowVerticalLines: true,
pointDot: false,
responsive: true
});
};
}());
</script>
</li>
@endforeach

View File

@@ -24,6 +24,9 @@ class Metric extends Model implements TransformableInterface
{
use ValidatingTrait;
const CALC_SUM = 0;
const CALC_AVG = 1;
/**
* The model's attributes.
*
@@ -32,6 +35,8 @@ class Metric extends Model implements TransformableInterface
protected $attributes = [
'name' => '',
'display_chart' => 1,
'default_value' => 0,
'calc_type' => 0,
];
/**
@@ -43,7 +48,7 @@ class Metric extends Model implements TransformableInterface
'name' => 'required',
'suffix' => 'required',
'display_chart' => 'boolean',
'default_value' => 'numeric|required',
'default_value' => 'numeric',
];
/**
@@ -51,7 +56,7 @@ class Metric extends Model implements TransformableInterface
*
* @var string[]
*/
protected $fillable = ['name', 'suffix', 'description', 'display_chart', 'default_value'];
protected $fillable = ['name', 'suffix', 'description', 'display_chart', 'default_value', 'calc_type'];
/**
* Metrics contain many metric points.
@@ -76,9 +81,20 @@ class Metric extends Model implements TransformableInterface
$dateTime->sub(new DateInterval('PT'.$hour.'H'));
if (Config::get('database.default') === 'mysql') {
$value = (int) $this->points()->whereRaw('DATE_FORMAT(created_at, "%Y%m%e%H") = '.$dateTime->format('YmdH'))->whereRaw('HOUR(created_at) = HOUR(DATE_SUB(NOW(), INTERVAL '.$hour.' HOUR))')->groupBy(DB::raw('HOUR(created_at)'))->sum('value');
if (! isset($this->calc_type) || $this->calc_type === self::CALC_SUM) {
$value = (int) $this->points()->whereRaw('DATE_FORMAT(created_at, "%Y%m%e%H") = '.$dateTime->format('YmdH'))->whereRaw('HOUR(created_at) = HOUR(DATE_SUB(NOW(), INTERVAL '.$hour.' HOUR))')->groupBy(DB::raw('HOUR(created_at)'))->sum('value');
} elseif ($this->calc_type === self::CALC_AVG) {
$value = (int) $this->points()->whereRaw('DATE_FORMAT(created_at, "%Y%m%e%H") = '.$dateTime->format('YmdH'))->whereRaw('HOUR(created_at) = HOUR(DATE_SUB(NOW(), INTERVAL '.$hour.' HOUR))')->groupBy(DB::raw('HOUR(created_at)'))->avg('value');
}
} else {
$query = DB::select("select sum(metric_points.value) as aggregate FROM metrics JOIN metric_points ON metric_points.metric_id = metrics.id WHERE to_char(metric_points.created_at, 'YYYYMMDDHH') = :timestamp AND to_char(metric_points.created_at, 'H') = to_char(now() - interval '{$hour} hour', 'H') GROUP BY to_char(metric_points.created_at, 'H')", [
// Default metrics calculations.
if (! isset($this->calc_type) || $this->calc_type === self::CALC_SUM) {
$queryType = "sum(metric_points.value)";
} elseif ($this->calc_type === self::CALC_AVG) {
$queryType = "avg(metric_points.value)";
}
$query = DB::select("select {$queryType} as aggregate FROM metrics JOIN metric_points ON metric_points.metric_id = metrics.id WHERE to_char(metric_points.created_at, 'YYYYMMDDHH') = :timestamp AND to_char(metric_points.created_at, 'H') = to_char(now() - interval '{$hour} hour', 'H') GROUP BY to_char(metric_points.created_at, 'H')", [
'timestamp' => $dateTime->format('YmdH'),
]);