mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-19 10:37:01 +00:00
Metrics improvements
- Label graphs by their duration, not update period - Extend to 60 units so they are either 10 minutes or an hour of data - Improvements to retention information - Change javascript calculations, fixes #9 (I hope)
This commit is contained in:
@@ -104,11 +104,12 @@ func metricsTicker(t *time.Ticker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pushMetric adds the metric to the end of the list and returns a comma
|
// pushMetric adds the metric to the end of the list and returns a comma separated string of the
|
||||||
// separated string of the previous 50 entries
|
// previous 61 entries. We return 61 instead of 60 (an hour) because the chart on the client
|
||||||
|
// tracks deltas between these values - there is nothing to compare the first value against.
|
||||||
func pushMetric(history *list.List, ev expvar.Var) string {
|
func pushMetric(history *list.List, ev expvar.Var) string {
|
||||||
history.PushBack(ev.String())
|
history.PushBack(ev.String())
|
||||||
if history.Len() > 50 {
|
if history.Len() > 61 {
|
||||||
history.Remove(history.Front())
|
history.Remove(history.Front())
|
||||||
}
|
}
|
||||||
return JoinStringList(history)
|
return JoinStringList(history)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ var retentionScanCompleted time.Time
|
|||||||
var retentionScanCompletedMu sync.RWMutex
|
var retentionScanCompletedMu sync.RWMutex
|
||||||
|
|
||||||
var expRetentionDeletesTotal = new(expvar.Int)
|
var expRetentionDeletesTotal = new(expvar.Int)
|
||||||
|
var expRetentionPeriod = new(expvar.Int)
|
||||||
|
|
||||||
// History of certain stats
|
// History of certain stats
|
||||||
var retentionDeletesHist = list.New()
|
var retentionDeletesHist = list.New()
|
||||||
@@ -22,6 +23,7 @@ var expRetentionDeletesHist = new(expvar.String)
|
|||||||
|
|
||||||
func StartRetentionScanner(ds DataStore) {
|
func StartRetentionScanner(ds DataStore) {
|
||||||
cfg := config.GetDataStoreConfig()
|
cfg := config.GetDataStoreConfig()
|
||||||
|
expRetentionPeriod.Set(int64(cfg.RetentionMinutes * 60))
|
||||||
if cfg.RetentionMinutes > 0 {
|
if cfg.RetentionMinutes > 0 {
|
||||||
// Retention scanning enabled
|
// Retention scanning enabled
|
||||||
log.Info("Retention configured for %v minutes", cfg.RetentionMinutes)
|
log.Info("Retention configured for %v minutes", cfg.RetentionMinutes)
|
||||||
@@ -109,4 +111,5 @@ func init() {
|
|||||||
rm.Set("SecondsSinceScanCompleted", expvar.Func(secondsSinceRetentionScanCompleted))
|
rm.Set("SecondsSinceScanCompleted", expvar.Func(secondsSinceRetentionScanCompleted))
|
||||||
rm.Set("DeletesHist", expRetentionDeletesHist)
|
rm.Set("DeletesHist", expRetentionDeletesHist)
|
||||||
rm.Set("DeletesTotal", expRetentionDeletesTotal)
|
rm.Set("DeletesTotal", expRetentionDeletesTotal)
|
||||||
|
rm.Set("Period", expRetentionPeriod)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ table.metrics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.metrics td.sparkline {
|
.metrics td.sparkline {
|
||||||
width: 170px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#emailAttachments {
|
#emailAttachments {
|
||||||
|
|||||||
@@ -42,8 +42,8 @@
|
|||||||
h = new Array(0)
|
h = new Array(0)
|
||||||
}
|
}
|
||||||
// Prevent array from growing
|
// Prevent array from growing
|
||||||
if (h.length >= 50) {
|
if (h.length >= 60) {
|
||||||
h = h.slice(1,50)
|
h = h.slice(1,60)
|
||||||
}
|
}
|
||||||
h.push(parseInt(value))
|
h.push(parseInt(value))
|
||||||
dataHist[name] = h
|
dataHist[name] = h
|
||||||
@@ -61,6 +61,10 @@
|
|||||||
h[i] = t-prev
|
h[i] = t-prev
|
||||||
prev = t
|
prev = t
|
||||||
}
|
}
|
||||||
|
// First value will always be zero
|
||||||
|
if (h.length > 0) {
|
||||||
|
h = h.slice(1)
|
||||||
|
}
|
||||||
el = $('#s-' + name)
|
el = $('#s-' + name)
|
||||||
if (el) {
|
if (el) {
|
||||||
el.sparkline(h)
|
el.sparkline(h)
|
||||||
@@ -86,6 +90,7 @@
|
|||||||
// Non graphing
|
// Non graphing
|
||||||
metric('uptime', data.uptime, timeFilter, false)
|
metric('uptime', data.uptime, timeFilter, false)
|
||||||
metric('retentionScanCompleted', data.retention.SecondsSinceScanCompleted, timeFilter, false)
|
metric('retentionScanCompleted', data.retention.SecondsSinceScanCompleted, timeFilter, false)
|
||||||
|
metric('retentionPeriod', data.retention.Period, timeFilter, false)
|
||||||
|
|
||||||
// JavaScript history
|
// JavaScript history
|
||||||
metric('memstatsSys', data.memstats.Sys, sizeFilter, true)
|
metric('memstatsSys', data.memstats.Sys, sizeFilter, true)
|
||||||
@@ -114,7 +119,7 @@
|
|||||||
|
|
||||||
function aboutInit() {
|
function aboutInit() {
|
||||||
loadMetrics()
|
loadMetrics()
|
||||||
setInterval(loadMetrics, 5000)
|
setInterval(loadMetrics, 10000)
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(aboutInit)
|
$(document).ready(aboutInit)
|
||||||
@@ -131,9 +136,8 @@
|
|||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<h2>Inbucket Status</h2>
|
<h2>Inbucket Status</h2>
|
||||||
|
|
||||||
<p>Metrics are polled every 5 seconds. Inbucket does not keep history for the
|
<p>Metrics are polled every 10 seconds. Inbucket does not keep history for the
|
||||||
graphs labeled <em>(5s)</em>, but your web browser will chart the last 50
|
10 minute graphs, but your web browser will accumulate the data over time.</p>
|
||||||
values over time.</p>
|
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<h3>General Metrics</h3>
|
<h3>General Metrics</h3>
|
||||||
@@ -146,25 +150,25 @@ values over time.</p>
|
|||||||
<th>System Memory:</th>
|
<th>System Memory:</th>
|
||||||
<td><span id="m-memstatsSys">.</span></td>
|
<td><span id="m-memstatsSys">.</span></td>
|
||||||
<td class="sparkline"><span id="s-memstatsSys">.</span></td>
|
<td class="sparkline"><span id="s-memstatsSys">.</span></td>
|
||||||
<td>(5s)</td>
|
<td>(10min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Heap Size:</th>
|
<th>Heap Size:</th>
|
||||||
<td><span id="m-memstatsHeapSys">.</span></td>
|
<td><span id="m-memstatsHeapSys">.</span></td>
|
||||||
<td class="sparkline"><span id="s-memstatsHeapSys">.</span></td>
|
<td class="sparkline"><span id="s-memstatsHeapSys">.</span></td>
|
||||||
<td>(5s)</td>
|
<td>(10min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Heap In-Use:</th>
|
<th>Heap In-Use:</th>
|
||||||
<td><span id="m-memstatsHeapAlloc">.</span></td>
|
<td><span id="m-memstatsHeapAlloc">.</span></td>
|
||||||
<td class="sparkline"><span id="s-memstatsHeapAlloc">.</span></td>
|
<td class="sparkline"><span id="s-memstatsHeapAlloc">.</span></td>
|
||||||
<td>(5s)</td>
|
<td>(10min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Heap # Objects:</th>
|
<th>Heap # Objects:</th>
|
||||||
<td><span id="m-memstatsHeapObjects">.</span></td>
|
<td><span id="m-memstatsHeapObjects">.</span></td>
|
||||||
<td class="sparkline"><span id="s-memstatsHeapObjects">.</span></td>
|
<td class="sparkline"><span id="s-memstatsHeapObjects">.</span></td>
|
||||||
<td>(5s)</td>
|
<td>(10min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<p class="last"> </p>
|
<p class="last"> </p>
|
||||||
@@ -176,31 +180,31 @@ values over time.</p>
|
|||||||
<th>Current Connections:</th>
|
<th>Current Connections:</th>
|
||||||
<td><span id="m-smtpConnectsCurrent">.</span></td>
|
<td><span id="m-smtpConnectsCurrent">.</span></td>
|
||||||
<td class="sparkline"><span id="s-smtpConnectsCurrent">.</span></td>
|
<td class="sparkline"><span id="s-smtpConnectsCurrent">.</span></td>
|
||||||
<td>(5s)</td>
|
<td>(10min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total Connections:</th>
|
<th>Total Connections:</th>
|
||||||
<td><span id="m-smtpConnectsTotal">.</span></td>
|
<td><span id="m-smtpConnectsTotal">.</span></td>
|
||||||
<td class="sparkline"><span id="s-smtpConnectsTotal">.</span></td>
|
<td class="sparkline"><span id="s-smtpConnectsTotal">.</span></td>
|
||||||
<td>(60s)</td>
|
<td>(60min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Messages Delivered:</th>
|
<th>Messages Delivered:</th>
|
||||||
<td><span id="m-smtpDeliveredTotal">.</span></td>
|
<td><span id="m-smtpDeliveredTotal">.</span></td>
|
||||||
<td class="sparkline"><span id="s-smtpDeliveredTotal">.</span></td>
|
<td class="sparkline"><span id="s-smtpDeliveredTotal">.</span></td>
|
||||||
<td>(60s)</td>
|
<td>(60min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Errors Logged:</th>
|
<th>Errors Logged:</th>
|
||||||
<td><span id="m-smtpErrorsTotal">.</span></td>
|
<td><span id="m-smtpErrorsTotal">.</span></td>
|
||||||
<td class="sparkline"><span id="s-smtpErrorsTotal"></span></td>
|
<td class="sparkline"><span id="s-smtpErrorsTotal"></span></td>
|
||||||
<td>(60s)</td>
|
<td>(60min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Warnings Logged:</th>
|
<th>Warnings Logged:</th>
|
||||||
<td><span id="m-smtpWarnsTotal">.</span></td>
|
<td><span id="m-smtpWarnsTotal">.</span></td>
|
||||||
<td class="sparkline"><span id="s-smtpWarnsTotal"></span></td>
|
<td class="sparkline"><span id="s-smtpWarnsTotal"></span></td>
|
||||||
<td>(60s)</td>
|
<td>(60min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<p class="last"> </p>
|
<p class="last"> </p>
|
||||||
@@ -208,15 +212,31 @@ values over time.</p>
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<h3>Data Store Metrics</h3>
|
<h3>Data Store Metrics</h3>
|
||||||
<table class="metrics">
|
<table class="metrics">
|
||||||
|
<tr>
|
||||||
|
<th>Retention Period:</th>
|
||||||
|
<td colspan="3">
|
||||||
|
{{if .retentionMinutes}}
|
||||||
|
<span id="m-retentionPeriod">.</span>
|
||||||
|
{{else}}
|
||||||
|
Disabled
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Retention Scan:</th>
|
<th>Retention Scan:</th>
|
||||||
<td colspan="3">Completed <span id="m-retentionScanCompleted">.</span> ago</td>
|
<td colspan="3">
|
||||||
|
{{if .retentionMinutes}}
|
||||||
|
Completed <span id="m-retentionScanCompleted">.</span> ago
|
||||||
|
{{else}}
|
||||||
|
Disabled
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Retention Deletes:</th>
|
<th>Retention Deletes:</th>
|
||||||
<td><span id="m-retentionDeletesTotal">.</span></td>
|
<td><span id="m-retentionDeletesTotal">.</span></td>
|
||||||
<td class="sparkline"><span id="s-retentionDeletesTotal"></span></td>
|
<td class="sparkline"><span id="s-retentionDeletesTotal"></span></td>
|
||||||
<td>(60s)</td>
|
<td>(60min)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<p class="last"> </p>
|
<p class="last"> </p>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package web
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jhillyerd/inbucket/config"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,7 +12,9 @@ func RootIndex(w http.ResponseWriter, req *http.Request, ctx *Context) (err erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RootStatus(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
|
func RootStatus(w http.ResponseWriter, req *http.Request, ctx *Context) (err error) {
|
||||||
|
retentionMinutes := config.GetDataStoreConfig().RetentionMinutes
|
||||||
return RenderTemplate("root/status.html", w, map[string]interface{}{
|
return RenderTemplate("root/status.html", w, map[string]interface{}{
|
||||||
"ctx": ctx,
|
"ctx": ctx,
|
||||||
|
"retentionMinutes": retentionMinutes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user