2018-10-02 06:21:14 +00:00
{ { define "title" } } { { . Service . Name } } Status { { end } }
2018-11-06 07:15:55 +00:00
{ { define "description" } } { { $ s := . Service } } { { if $ s . Online } } { { . Service . Name } } is currently online and responding within { { $ s . AvgTime } } milliseconds with { { $ s . TotalUptime } } % total uptime on { { $ s . Domain } } . { { else } } { { . Service . Name } } is currently offline on { { $ s . Domain } } . Notify the admin to let them know their service is offline . { { end } } { { end } }
2018-10-02 06:21:14 +00:00
{ { define "content" } }
2018-09-18 22:02:27 +00:00
{ { $ s := . Service } }
2019-01-04 06:16:44 +00:00
{ { $ failures := $ s . LimitedFailures 16 } }
2019-06-24 22:21:38 +00:00
{ { $ incidents := $ s . Incidents } }
2019-01-04 06:16:44 +00:00
{ { $ checkinFailures := $ s . LimitedCheckinFailures 16 } }
2018-12-18 05:25:33 +00:00
{ { $ isAdmin := Auth } }
2018-06-24 11:51:07 +00:00
< div class = "container col-md-7 col-sm-12 mt-md-5 bg-light" >
2018-06-11 03:41:02 +00:00
2018-12-18 05:25:33 +00:00
{ { if IsUser } }
2018-06-11 03:41:02 +00:00
{ { template "nav" } }
{ { end } }
2018-10-02 06:21:14 +00:00
< div class = "col-12 mb-4" >
2018-06-11 03:41:02 +00:00
2018-11-07 05:06:44 +00:00
{ { if $ s . Online } }
< span class = "mt-3 mb-3 text-white d-md-none btn bg-success d-block d-md-none" > ONLINE < / span >
{ { else } }
< span class = "mt-3 mb-3 text-white d-md-none btn bg-danger d-block d-md-none" > OFFLINE < / span >
{ { end } }
2018-10-02 06:21:14 +00:00
2019-02-01 04:48:18 +00:00
< h4 class = "mt-2" > < a href = "/" > { { CoreApp . Name } } < / a > - { { $ s . Name } }
2018-10-02 06:21:14 +00:00
{ { if $ s . Online } }
< span class = "badge bg-success float-right d-none d-md-block" > ONLINE < / span >
{ { else } }
< span class = "badge bg-danger float-right d-none d-md-block" > OFFLINE < / span >
{ { end } } < / h4 >
2018-06-11 03:41:02 +00:00
2018-10-02 06:21:14 +00:00
< div class = "row stats_area mt-5 mb-5" >
< div class = "col-4" >
2019-02-01 04:48:18 +00:00
< span class = "lg_number" > { { $ s . OnlineDaysPercent 1 } } % < / span >
2018-10-02 06:21:14 +00:00
Online last 24 Hours
< / div >
< div class = "col-4" >
< span class = "lg_number" > { { $ s . AvgTime } } ms < / span >
Average Response
2018-06-22 04:02:57 +00:00
< / div >
2018-10-02 06:21:14 +00:00
< div class = "col-4" >
< span class = "lg_number" > { { $ s . TotalUptime } } % < / span >
Total Uptime
< / div >
< / div >
2018-11-07 08:53:37 +00:00
{ { if $ s . ActiveMessages } }
2018-11-16 16:42:49 +00:00
< div class = "col-12 mb-5" >
2018-12-18 05:25:33 +00:00
{ { range $ s . ActiveMessages } }
< div class = "alert alert-warning" role = "alert" >
< h3 > { { . Title } } < / h3 >
< span class = "mb-3" > { { safe . Description } } < / span >
< div class = "d-block mt-2 mb-4" >
< span class = "float-left small" > Starts at { { . StartOn } } < / span >
< span class = "float-right small" > Ends on { { . EndOn } } < / span >
< / div >
2018-11-16 16:42:49 +00:00
< / div >
2018-12-18 05:25:33 +00:00
{ { end } }
2018-11-07 08:53:37 +00:00
< / div >
{ { end } }
2018-10-02 06:21:14 +00:00
< div class = "service-chart-container" >
2019-01-29 12:02:13 +00:00
< div id = "service" > < / div >
2019-02-01 19:57:59 +00:00
< div id = "service-bar" > < / div >
2019-01-29 12:02:13 +00:00
< / div >
2019-02-01 04:48:18 +00:00
< div class = "service-chart-heatmap" >
2019-01-29 12:02:13 +00:00
< div id = "service_heatmap" > < / div >
2018-10-02 06:21:14 +00:00
< / div >
< form id = "service_date_form" class = "col-12 mt-2 mb-3" >
2018-11-07 05:06:44 +00:00
< input type = "text" class = "d-none" name = "start" id = "service_start" data - input >
< span data - toggle title = "toggle" id = "start_date" class = "text-muted small float-left pointer mt-2" > { { . Start } } to { { . End } } < / span >
< button type = "submit" class = "btn btn-light btn-sm mt-2" > Set Timeframe < / button >
< input type = "text" class = "d-none" name = "end" id = "service_end" data - input >
2018-10-02 06:21:14 +00:00
< div id = "start_container" > < / div >
< div id = "end_container" > < / div >
< / form >
{ { if not $ s . Online } }
< div class = "col-12 small text-center mt-3 text-muted" > { { $ s . DowntimeText } } < / div >
{ { end } }
2018-12-18 05:25:33 +00:00
{ { if IsUser } }
2018-11-28 20:01:10 +00:00
< nav class = "nav nav-pills flex-column flex-sm-row mt-3" id = "service_tabs" role = "serviceLists" >
2018-12-18 05:25:33 +00:00
{ { if $ isAdmin } } < a class = "flex-sm-fill text-sm-center nav-link active" id = "edit-tab" data - toggle = "tab" href = "#edit" role = "tab" aria - controls = "edit" aria - selected = "false" > Edit Service < / a > { { end } }
< a class = "flex-sm-fill text-sm-center nav-link{{ if not $failures }} disabled{{end}}" id = "failures-tab" data - toggle = "tab" href = "#failures" role = "tab" aria - controls = "failures" aria - selected = "true" > Failures < / a >
2019-06-24 22:21:38 +00:00
< a class = "flex-sm-fill text-sm-center nav-link{{ if not $incidents }} disabled{{end}}" id = "incidents-tab" data - toggle = "tab" href = "#incidents" role = "tab" aria - controls = "incidents" aria - selected = "true" > Incidents < / a >
2018-12-18 05:25:33 +00:00
{ { if $ isAdmin } } < a class = "flex-sm-fill text-sm-center nav-link" id = "checkins-tab" data - toggle = "tab" href = "#checkins" role = "tab" aria - controls = "checkins" aria - selected = "false" > Checkins < / a > { { end } }
< a class = "flex-sm-fill text-sm-center nav-link{{if not $isAdmin}} active{{end}}" id = "response-tab" data - toggle = "tab" href = "#response" role = "tab" aria - controls = "response" aria - selected = "false" > Response < / a >
2018-11-28 20:01:10 +00:00
< / nav >
< div class = "tab-content" id = "myTabContent" >
2018-12-18 05:25:33 +00:00
{ { if $ isAdmin } }
2018-11-29 09:10:33 +00:00
< div class = "tab-pane fade" id = "failures" role = "serviceLists" aria - labelledby = "failures-tab" >
2018-11-28 20:01:10 +00:00
{ { if $ failures } }
< div class = "list-group mt-3 mb-4" >
{ { range $ failures } }
< a href = "#" class = "list-group-item list-group-item-action flex-column align-items-start" >
< div class = "d-flex w-100 justify-content-between" >
< h5 class = "mb-1" > { { . ParseError } } < / h5 >
< small > { { . Ago } } < / small >
< / div >
< p class = "mb-1" > { { . Issue } } < / p >
< / a >
{ { end } }
2018-10-02 06:21:14 +00:00
< / div >
2018-11-28 20:01:10 +00:00
{ { end } }
2018-06-23 08:42:50 +00:00
< / div >
2018-12-18 05:25:33 +00:00
{ { end } }
2019-06-24 22:21:38 +00:00
< div class = "tab-pane fade" id = "incidents" role = "serviceLists" aria - labelledby = "incidents-tab" >
{ { if $ incidents } }
< div class = "list-group mt-3 mb-4" >
{ { range $ incidents } }
< div class = "list-group-item flex-column align-items-start" >
< div class = "d-flex w-100 justify-content-between" >
< h5 class = "mb-1" > { { . Title } } < / h5 >
< small > { { . CreatedAt } } < / small >
< / div >
< p class = "mb-1" > { { . Description } } < / p >
< ul class = "list-group mt-3" >
{ { range . AllUpdates } }
< li class = "list-group-item" >
< p >
< span class = "badge badge-primary" > { { . Type } } < / span >
< span class = "float-right" >
{ { . Message } }
< p class = "text-muted text-right small" > { { . CreatedAt } } < / p >
< / span >
< / p >
< / li >
{ { end } }
< / ul >
< / div >
{ { end } }
< / div >
{ { end } }
< / div >
2018-12-18 05:25:33 +00:00
{ { if $ isAdmin } }
2018-11-28 20:01:10 +00:00
< div class = "tab-pane fade" id = "checkins" role = "serviceLists" aria - labelledby = "checkins-tab" >
2018-12-06 19:03:55 +00:00
{ { if $ s . AllCheckins } }
2018-11-28 20:01:10 +00:00
< table class = "table" >
< thead >
< tr >
< th scope = "col" > Checkin < / th >
< th scope = "col" > Report Period < br > Grace Period < / th >
< th scope = "col" > Last Seen < / th >
< th scope = "col" > Expected < / th >
< th scope = "col" > < / th >
< / tr >
< / thead >
< tbody style = "font-size: 10pt;" >
2018-12-06 19:03:55 +00:00
{ { range $ s . AllCheckins } }
2018-11-28 20:01:10 +00:00
{ { $ ch := . } }
< tr id = "checkin_{{$ch.Id}}" class = "{{ if lt $ch.Expected 0}}bg-warning text-black{{else}}bg-light{{end}}" >
< td > { { $ ch . Name } } < br > < a href = "{{$ch.Link}}" target = "_blank" > { { $ ch . Link } } < / a > < / td >
< td > every { { Duration $ ch . Period } } < br > after { { Duration $ ch . Grace } } < / td >
< td > { { if $ ch . Last . CreatedAt . IsZero } }
Never
{ { else } }
2018-10-07 22:38:56 +00:00
{ { Ago $ ch . Last . CreatedAt } }
{ { end } }
2018-11-28 20:01:10 +00:00
< / td >
< td >
{ { if $ ch . Last . CreatedAt . IsZero } }
-
{ { else } }
2018-10-07 22:38:56 +00:00
{ { if lt $ ch . Expected 0 } } { { Duration $ ch . Expected } } ago { { else } } in { { Duration $ ch . Expected } } { { end } }
2018-11-28 20:01:10 +00:00
{ { end } }
< / td >
< td > < a href = "/api/checkin/{{$ch.ApiKey}}" data - method = "DELETE" data - obj = "checkin_{{$ch.Id}}" data - id = "{{$ch.Id}}" class = "ajax_delete btn btn-sm btn-danger" > Delete < / a > < / td >
< / tr >
2018-10-07 22:38:56 +00:00
{ { end } }
2018-11-28 20:01:10 +00:00
< / tbody >
< / table >
2018-10-06 03:35:53 +00:00
{ { end } }
2018-12-18 05:25:33 +00:00
{ { if $ isAdmin } }
{ { template "form_checkin" $ s } }
{ { end } }
2019-01-04 06:16:44 +00:00
{ { if $ checkinFailures } }
2018-11-28 20:01:10 +00:00
< div class = "list-group mt-3 mb-4" >
2019-01-04 06:16:44 +00:00
{ { range $ checkinFailures } }
2018-11-28 20:01:10 +00:00
< a href = "#" class = "list-group-item list-group-item-action flex-column align-items-start" >
< div class = "d-flex w-100 justify-content-between" >
< h5 class = "mb-1" > { { . ParseError } } < / h5 >
< small > { { . Ago } } < / small >
< / div >
< p class = "mb-1" > { { . Issue } } < / p >
< / a >
{ { end } }
< / div >
{ { end } }
< / div >
2018-12-18 05:25:33 +00:00
{ { end } }
< div class = "tab-pane fade{{if not $isAdmin}} show active{{end}}" id = "response" role = "serviceLists" aria - labelledby = "response-tab" >
2018-11-28 20:01:10 +00:00
< div class = "col-12 mt-4{{if ne $s.Type " http "}} d-none{{end}}" >
< h3 > Last Response < / h3 >
< textarea rows = "8" class = "form-control" readonly > { { $ s . LastResponse } } < / textarea >
< div class = "form-group row mt-2" >
< label for = "last_status_code" class = "col-sm-3 col-form-label" > HTTP Status Code < / label >
< div class = "col-sm-2" >
< input type = "text" id = "last_status_code" class = "form-control" value = "{{ $s.LastStatusCode }}" readonly >
< / div >
< / div >
< / div >
< / div >
2018-12-18 05:25:33 +00:00
{ { if $ isAdmin } }
2018-11-29 09:10:33 +00:00
< div class = "tab-pane fade show active" id = "edit" role = "serviceLists" aria - labelledby = "edit-tab" >
2018-11-28 20:01:10 +00:00
{ { template "form_service" $ s } }
< / div >
2018-12-18 05:25:33 +00:00
{ { end } }
2018-11-28 20:01:10 +00:00
< / div >
2019-01-04 06:16:44 +00:00
{ { else } }
{ { if $ s . Public . Bool } }
{ { if $ failures } }
< div class = "list-group mt-3 mb-4" >
{ { range $ failures } }
< a href = "#" class = "list-group-item list-group-item-action flex-column align-items-start" >
< div class = "d-flex w-100 justify-content-between" >
< h5 class = "mb-1" > { { . ParseError } } < / h5 >
< small > { { . Ago } } < / small >
< / div >
< p class = "mb-1" > { { . Issue } } < / p >
< / a >
{ { end } }
< / div >
{ { end } }
{ { end } }
2018-06-30 19:30:58 +00:00
{ { end } }
2018-06-30 03:40:00 +00:00
< / div >
2018-12-18 05:25:33 +00:00
< / div >
2018-10-02 06:21:14 +00:00
{ { end } }
2018-11-07 05:06:44 +00:00
{ { define "extra_css" } }
< link rel = "stylesheet" href = "/css/flatpickr.min.css" >
2018-07-07 05:02:47 +00:00
{ { end } }
2018-11-07 05:06:44 +00:00
{ { define "extra_scripts" } }
2018-10-02 06:21:14 +00:00
{ { $ s := . Service } }
2018-11-07 05:06:44 +00:00
< script src = "/js/flatpickr.js" > < / script >
< script src = "/js/rangePlugin.js" > < / script >
2018-09-18 22:02:27 +00:00
< script >
2018-09-21 04:17:24 +00:00
2019-02-01 04:48:18 +00:00
let options = {
chart : {
height : "100%" ,
width : "100%" ,
type : "area" ,
animations : {
enabled : false ,
initialAnimation : {
enabled : false
}
} ,
} ,
fill : {
colors : [ "#48d338" ] ,
opacity : 1 ,
type : ' solid '
} ,
stroke : {
show : true ,
curve : ' smooth ' ,
lineCap : ' butt ' ,
colors : [ "#3aa82d" ] ,
} ,
2019-02-20 02:11:40 +00:00
series : [ { data : [ { } ] } ] ,
2019-02-01 04:48:18 +00:00
xaxis : {
type : "datetime" ,
2019-02-01 19:57:59 +00:00
tickAmount : 8 ,
2019-02-01 04:48:18 +00:00
} ,
yaxis : {
labels : {
formatter : ( value ) = > {
return ( value ) . toFixed ( 0 ) + "ms"
2018-09-21 04:17:24 +00:00
} ,
2019-01-29 12:02:13 +00:00
} ,
2019-02-01 04:48:18 +00:00
} ,
dataLabels : {
enabled : false
} ,
} ;
var heat_options = {
chart : {
height : "100%" ,
width : "100%" ,
type : ' heatmap ' ,
toolbar : {
show : false
}
} ,
dataLabels : {
enabled : false ,
} ,
enableShades : true ,
shadeIntensity : 0.5 ,
colors : [ "#d53a3b" ] ,
2019-02-20 02:11:40 +00:00
series : [ { data : [ { } ] } ] ,
2019-02-01 04:48:18 +00:00
yaxis : {
labels : {
formatter : ( value ) = > {
return value
} ,
2019-01-29 12:02:13 +00:00
} ,
2019-02-01 04:48:18 +00:00
} ,
tooltip : {
enabled : true ,
x : {
show : false ,
2019-01-29 12:02:13 +00:00
} ,
2019-02-01 04:48:18 +00:00
y : {
formatter : function ( val , opts ) { return val + " Failures" } ,
title : {
formatter : ( seriesName ) = > seriesName ,
2019-01-29 12:02:13 +00:00
} ,
} ,
2019-02-01 04:48:18 +00:00
}
} ;
2018-09-21 04:17:24 +00:00
2019-12-04 14:41:40 +00:00
async function zoomedEvent ( chart , { xaxis , yaxis } ) {
let start = Math . round ( xaxis . min / 1000 ) ,
end = Math . round ( xaxis . max / 1000 ) ;
let chartData = await ChartLatency ( { { $ s . Id } } , start , end ) ;
if ( ! chartData ) {
chartData = await ChartLatency ( { { $ s . Id } } , start , end , "minute" ) ;
}
if ( ! chartData || ! chartData . length ) {
return false
}
chart . updateSeries ( [ { data : chartData } ] ) ;
}
2019-01-29 12:02:13 +00:00
2019-02-01 04:48:18 +00:00
async function RenderHeatmap ( ) {
let heatChart = new ApexCharts (
document . querySelector ( "#service_heatmap" ) ,
heat_options
) ;
let dataArr = [ ] ;
let heatmapData = await ChartHeatmap ( { { $ s . Id } } ) ;
heatmapData . forEach ( function ( d ) {
var date = new Date ( d . date ) ;
dataArr . push ( { name : date . toLocaleString ( ' en - us ' , { month : ' long ' } ) , data : d . data } ) ;
} ) ;
heatChart . render ( ) ;
heatChart . updateSeries ( dataArr ) ;
}
async function RenderChartLatency ( ) {
2019-12-04 14:41:40 +00:00
options . chart . events = {
zoomed : zoomedEvent ,
}
options . fill . colors = { { if $ s . Online } } [ "#48d338" ] { { else } } [ "#dd3545" ] { { end } } ;
options . stroke . colors = { { if $ s . Online } } [ "#3aa82d" ] { { else } } [ "#c23342" ] { { end } } ;
2019-02-01 04:48:18 +00:00
let chart = new ApexCharts ( document . querySelector ( "#service" ) , options ) ;
await RenderChart ( chart , { { $ s . Id } } , { { . StartUnix } } , { { . EndUnix } } , "hour" ) ;
}
2018-09-21 04:17:24 +00:00
2019-02-01 04:48:18 +00:00
$ ( document ) . ready ( async function ( ) {
2019-04-20 04:43:07 +00:00
2018-11-07 05:06:44 +00:00
let startDate = $ ( "#service_start" ) . flatpickr ( {
enableTime : false ,
static : true ,
altInput : true ,
altFormat : "U" ,
maxDate : "today" ,
dateFormat : "F j, Y" ,
onChange : function ( selectedDates , dateStr , instance ) {
var one = Math . round ( ( new Date ( selectedDates [ 0 ] ) ) . getTime ( ) / 1000 ) ;
var two = Math . round ( ( new Date ( selectedDates [ 1 ] ) ) . getTime ( ) / 1000 ) ;
2019-02-01 04:48:18 +00:00
$ ( "#service_start" ) . val ( one ) ;
2018-11-07 05:06:44 +00:00
$ ( "#service_end" ) . val ( two ) ;
$ ( "#start_date" ) . html ( dateStr ) ;
} ,
"plugins" : [ new rangePlugin ( { input : "#service_end" } ) ]
2018-09-18 22:02:27 +00:00
} ) ;
$ ( "#start_date" ) . click ( function ( e ) {
2018-11-07 05:06:44 +00:00
startDate . open ( )
2018-10-07 22:38:56 +00:00
} ) ;
2018-09-18 22:02:27 +00:00
2019-02-01 04:48:18 +00:00
await RenderChartLatency ( ) ;
await RenderHeatmap ( ) ;
2019-01-29 12:02:13 +00:00
2018-11-07 05:06:44 +00:00
} ) ;
2018-09-18 22:02:27 +00:00
< / script >
2018-10-02 06:21:14 +00:00
{ { end } }