dashing-contrib 0.0.5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/README.md +88 -32
- data/dashing-contrib.gemspec +3 -1
- data/lib/dashing-contrib.rb +11 -1
- data/lib/dashing-contrib/assets/widgets.scss +31 -1
- data/lib/dashing-contrib/assets/widgets/dashing_state/dashing_state.coffee +11 -0
- data/lib/dashing-contrib/assets/widgets/dashing_state/dashing_state.html +24 -0
- data/lib/dashing-contrib/assets/widgets/dashing_state/dashing_state.scss +48 -0
- data/lib/dashing-contrib/assets/widgets/kue_status/kue_status.html +10 -8
- data/lib/dashing-contrib/assets/widgets/kue_status/kue_status.scss +10 -8
- data/lib/dashing-contrib/assets/widgets/nagios_list/nagios_list.coffee +49 -0
- data/lib/dashing-contrib/assets/widgets/nagios_list/nagios_list.html +37 -0
- data/lib/dashing-contrib/assets/widgets/nagios_list/nagios_list.scss +61 -0
- data/lib/dashing-contrib/assets/widgets/pingdom_uptime/pingdom_uptime.html +33 -33
- data/lib/dashing-contrib/assets/widgets/pingdom_uptime/pingdom_uptime.scss +1 -1
- data/lib/dashing-contrib/assets/widgets/sidekiq/README.md +12 -18
- data/lib/dashing-contrib/assets/widgets/sidekiq/sidekiq.html +10 -8
- data/lib/dashing-contrib/assets/widgets/sidekiq/sidekiq.scss +10 -45
- data/lib/dashing-contrib/bottles/dashing.rb +40 -0
- data/lib/dashing-contrib/bottles/nagios.rb +1 -0
- data/lib/dashing-contrib/bottles/nagios/client.rb +4 -0
- data/lib/dashing-contrib/bottles/nagios/status.rb +29 -0
- data/lib/dashing-contrib/bottles/pingdom/checks.rb +1 -1
- data/lib/dashing-contrib/jobs/dashing-state.rb +19 -0
- data/lib/dashing-contrib/jobs/kue.rb +33 -0
- data/lib/dashing-contrib/jobs/nagios_list.rb +34 -0
- data/lib/dashing-contrib/jobs/pingdom_uptime.rb +58 -0
- data/lib/dashing-contrib/jobs/sidekiq.rb +32 -0
- data/lib/dashing-contrib/routes.rb +7 -0
- data/lib/dashing-contrib/runnable_job.rb +88 -0
- data/lib/dashing-contrib/version.rb +1 -1
- data/spec/jobs/sidekiq_spec.rb +25 -0
- data/spec/runnable_job_spec.rb +22 -0
- data/spec/spec_helper.rb +1 -0
- metadata +48 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f910eb445f25ea5ea1ba28bc77a4197224879a0
|
4
|
+
data.tar.gz: c90b294dcf58caa1b61a40dd9a497f2dc584891c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9512cfb5954f4cc079e9df977d776544b4cb8af78043eb8860f51bc4183ff6495b4704a627934ea4d173bd5bf182881012b376b201fbe2dddbc7fd5b91b37e6
|
7
|
+
data.tar.gz: 7739802b0ac7fb6adaf9e23bfd0a50ff127ef418e02d391cc7c89b029a0fef212eae1f9096a04dbb9f7c7097975a7dbed7518787e67a9af52e07906bd0b119ca
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -3,21 +3,23 @@
|
|
3
3
|
[](https://travis-ci.org/QubitProducts/dashing-contrib)
|
4
4
|
|
5
5
|
|
6
|
-
This project is an extension to Shopify's Dashing.
|
7
|
-
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
6
|
+
This project is an extension to Shopify's Dashing. Including this rubygem you will be able to:
|
7
|
+
|
8
|
+
* Use all the built-in widgets
|
9
|
+
* Extend `DashingContrib::RunnableJob` module to define, test jobs
|
10
|
+
* Built-in jobs are only a couple of lines implementation, no repetitive copy and paste
|
11
|
+
* Existing secret parameters is automatically loaded from `.env` file
|
12
|
+
* All jobs have a final state (ok, warning, critical)
|
13
|
+
* Additional Rest API to get overall state summary
|
12
14
|
|
13
|
-
Read each individual widget documentation to use dashing-contrib built-in widgets
|
15
|
+
Read each individual widget documentation to use dashing-contrib built-in widgets after the installation steps.
|
14
16
|
|
15
17
|
## Installation
|
16
18
|
Add this line to your Dashing's dashboard Gemfile:
|
17
19
|
|
18
|
-
gem 'dashing-contrib', '~> 0.0
|
20
|
+
gem 'dashing-contrib', '~> 0.1.0'
|
19
21
|
|
20
|
-
|
22
|
+
Update dependencies:
|
21
23
|
|
22
24
|
$ bundle
|
23
25
|
|
@@ -28,19 +30,28 @@ Add the following on top of the `config.ru`
|
|
28
30
|
require 'dashing'
|
29
31
|
DashingContrib.configure
|
30
32
|
|
31
|
-
|
33
|
+
Include built-in CoffeeScript to `assets/javascripts/application.coffee`
|
32
34
|
|
33
35
|
#=require dashing-contrib/assets/widgets
|
34
36
|
|
35
|
-
|
37
|
+
Include built-in SCSS to `assets/stylesheets/application.scss`
|
36
38
|
|
37
39
|
//=require dashing-contrib/assets/widgets
|
38
40
|
|
39
|
-
|
41
|
+
Now you will be able to use the following widgets, click to see individual documentation:
|
42
|
+
|
43
|
+
* [Rickshawgraph](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/rickshawgraph)
|
44
|
+
* [Sidekiq](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/sidekiq)
|
45
|
+
* [Pingdom Uptime](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/pingdom_uptime)
|
46
|
+
* [Kue Status](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/kue_status)
|
47
|
+
* [Nagios List](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/nagios_list)
|
48
|
+
* Dashing State
|
49
|
+
|
50
|
+
## dotenv
|
40
51
|
|
41
52
|
Shared job parameters are managed by `dotenv` gem. Add a `.env` file in your dashing project root. dashing-contrib will load your configuration from `.env` file automatically. An example `.env` file:
|
42
53
|
|
43
|
-
|
54
|
+
```ruby
|
44
55
|
NAGIOS_ENDPOINT: http://example.com/nagios3/cgi-bin
|
45
56
|
NAGIOS_USERNAME: dasher
|
46
57
|
NAGIOS_PASSWORD: readonly
|
@@ -48,34 +59,79 @@ NAGIOS_PASSWORD: readonly
|
|
48
59
|
PINGDOM_USERNAME: ping
|
49
60
|
PINGDOM_PASSWORD: pong
|
50
61
|
PINGDOM_API_KEY: pingpongpingpong
|
51
|
-
|
62
|
+
```
|
52
63
|
|
53
64
|
These values can be accessed in jobs `ENV['NAGIOS_ENDPOINT']`
|
54
65
|
|
55
|
-
## Widgets Doc
|
56
66
|
|
57
|
-
|
58
|
-
* [Sidekiq](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/sidekiq) made by [pallan](https://github.com/pallan)
|
59
|
-
* [Pingdom Uptime](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/pingdom_uptime) inspired by [Edools](https://github.com/Edools/dashing-pingdom)
|
60
|
-
* [Kue Status](https://github.com/QubitProducts/dashing-contrib/tree/master/lib/dashing-contrib/assets/widgets/kue_status)
|
61
|
-
|
62
|
-
## Job Helpers Doc
|
67
|
+
## Job Definition
|
63
68
|
|
64
|
-
|
65
|
-
|
66
|
-
## How to contribute
|
69
|
+
dashing-contrib gem provides a standard job definition wrapper. This replaces the 'SCHEDULE.every' call:
|
67
70
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
+
* defines common data processing and testable/reusable modules
|
72
|
+
* in addition to dashing's default 'updatedAt', introduced an optional `state` information used across all widgets
|
73
|
+
|
71
74
|
|
72
|
-
|
75
|
+
A custom job declaration example:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
module MyCustomJob
|
79
|
+
# provides some dashing hooks
|
80
|
+
extend DashingContrib::RunnableJob
|
81
|
+
|
82
|
+
# Overrides to extract some data for display
|
83
|
+
# generated hash will be available for widget to access
|
84
|
+
def self.metrics(options)
|
85
|
+
{ metrics: { failed: 500, ok: 123013 } }
|
86
|
+
end
|
87
|
+
|
88
|
+
# By default this always returns OK state
|
89
|
+
# You can customize the state return value by lookup generated metrics and user provided options
|
90
|
+
def self.validate_state(metrics, options = {})
|
91
|
+
# `metrics` parameter is the value return by `metrics` method
|
92
|
+
failed_value = metrics[:metrics][:failed]
|
93
|
+
|
94
|
+
return DashingContrib::RunnableJob::OK if failed_value == 0
|
95
|
+
return DashingContrib::RunnableJob::WARNING if failed_value <= 100
|
96
|
+
DashingContrib::RunnableJob::CRITICAL
|
97
|
+
end
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
When using job:
|
102
|
+
```ruby
|
103
|
+
# make sure MyCustomJob module is required
|
104
|
+
# default interval is every 30s and job is executed once at start
|
105
|
+
MyCustomJob.run(event: 'custom-job-event', every: '20s')
|
106
|
+
|
107
|
+
# Custom job also has a block syntax if you are setting up some global settings
|
108
|
+
MyCustomJob.run(event: 'custom-job-event') do
|
109
|
+
# setup redis client etc
|
110
|
+
end
|
111
|
+
|
112
|
+
# metrics and validate_state method will be able to use `my_custom_param` and `custom_threshold`
|
113
|
+
# to make configurable metrics fetch and state validation
|
114
|
+
MyCustomJob.run(event: 'custom-job-event', my_custom_param: 123, custom_threshold: 3)
|
115
|
+
```
|
116
|
+
|
117
|
+
|
118
|
+
Take a look some build-in jobs as example:
|
119
|
+
|
120
|
+
* [dashing-contrib/jobs/sidekiq.rb](https://github.com/QubitProducts/dashing-contrib/blob/master/lib/dashing-contrib/jobs/sidekiq.rb)
|
121
|
+
* [dashing-contrib/jobs/kue.rb](https://github.com/QubitProducts/dashing-contrib/blob/master/lib/dashing-contrib/jobs/kue.rb)
|
122
|
+
* [dashing-contrib/jobs/nagios_list.rb](https://github.com/QubitProducts/dashing-contrib/blob/master/lib/dashing-contrib/jobs/nagios_list.rb)
|
123
|
+
* [dashing-contrib/jobs/pingdom_uptime.rb](https://github.com/QubitProducts/dashing-contrib/blob/master/lib/dashing-contrib/jobs/pingdom_uptime.rb)
|
124
|
+
* [dashing-contrib/jobs/dashing-state.rb](https://github.com/QubitProducts/dashing-contrib/blob/master/lib/dashing-contrib/jobs/dashing-state.rb)
|
125
|
+
|
126
|
+
This is nice that backend data fetching can be now unit tested and reused. Dashing widget view layer can reuse the same job processor and present data in multiple forms.
|
73
127
|
|
74
|
-
#### Jobs utils
|
75
128
|
|
76
|
-
Common Job data processing for graphing purpose.
|
77
129
|
|
78
|
-
|
130
|
+
## How to contribute
|
79
131
|
|
80
|
-
|
132
|
+
There are a couple of ways to contribute. Brining those widgets scattered in github, in multiple format into this repository. They usually falling into the following categories:
|
81
133
|
|
134
|
+
* Widgets, common widgets should be generic solution to a common requirements. e.g. line graph, better clock with common functionalities. Documentation should be written as a README.md file under widget's own directory, include a preview.png file in the widget folder.
|
135
|
+
* Jobs utils, common Job data processing for graphing purpose
|
136
|
+
* Fix and add test
|
137
|
+
* Improve documentation
|
data/dashing-contrib.gemspec
CHANGED
@@ -25,7 +25,9 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency 'time_diff', '~> 0.3.0'
|
26
26
|
spec.add_dependency 'sidekiq', '~> 3.0.0'
|
27
27
|
spec.add_dependency 'activesupport', '~> 4.1.1'
|
28
|
-
spec.add_dependency 'sinatra'
|
28
|
+
spec.add_dependency 'sinatra', '~> 1.4.4'
|
29
|
+
spec.add_dependency 'dashing', '~> 1.3.4'
|
30
|
+
spec.add_dependency 'nagiosharder'
|
29
31
|
|
30
32
|
spec.add_development_dependency 'rake'
|
31
33
|
spec.add_development_dependency 'rspec'
|
data/lib/dashing-contrib.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
require 'active_support/all'
|
2
2
|
require 'dashing-contrib/version'
|
3
|
+
|
4
|
+
# configuration helpers
|
3
5
|
require 'dashing-contrib/configuration'
|
6
|
+
|
7
|
+
# history module and overall states management
|
4
8
|
require 'dashing-contrib/history'
|
5
|
-
require 'dashing-contrib/
|
9
|
+
require 'dashing-contrib/bottles/dashing'
|
6
10
|
require 'dashing-contrib/bottles/time'
|
11
|
+
|
12
|
+
# additional routes
|
13
|
+
require 'dashing-contrib/routes'
|
14
|
+
|
15
|
+
# contrib job extension
|
16
|
+
require 'dashing-contrib/runnable_job'
|
7
17
|
require 'dotenv'
|
8
18
|
|
9
19
|
|
@@ -1,3 +1,33 @@
|
|
1
1
|
//=require_tree ./javascripts
|
2
2
|
//=require_tree ./widgets
|
3
|
-
//=require ./stylesheets/font-awesome/scss/font-awesome
|
3
|
+
//=require ./stylesheets/font-awesome/scss/font-awesome
|
4
|
+
|
5
|
+
|
6
|
+
.dashing-contrib {
|
7
|
+
height: 100%;
|
8
|
+
width: 100%;
|
9
|
+
background-color: #2a2a2a;
|
10
|
+
font-size: 20px;
|
11
|
+
color: white;
|
12
|
+
|
13
|
+
.title {
|
14
|
+
font-size: 25px;
|
15
|
+
padding: 5px 10px;
|
16
|
+
color: white;
|
17
|
+
}
|
18
|
+
&.state-ok {
|
19
|
+
.title {
|
20
|
+
background-color: #272727;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
&.state-warning {
|
24
|
+
.title {
|
25
|
+
background-color: #F7CE1B;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
&.state-critical {
|
29
|
+
.title {
|
30
|
+
background-color: #C32026;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<div data-bind-class="state | prepend 'dashing-contrib state-'">
|
2
|
+
<div class="basic-stats">
|
3
|
+
<div class="stats-item ok">
|
4
|
+
<div data-bind="ok"></div>
|
5
|
+
<div class="stats-title">OK</div>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<div class="stats-item warning">
|
9
|
+
<div data-bind="warning"></div>
|
10
|
+
<div class="stats-title">WARNING</div>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div class="stats-item critical">
|
14
|
+
<div data-bind="critical"></div>
|
15
|
+
<div class="stats-title">CRITICAL</div>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
</div>
|
19
|
+
<ul>
|
20
|
+
<li data-foreach-item="items" data-bind-class="item.state | prepend 'item-state-'">
|
21
|
+
<span data-bind="item.title"></span>
|
22
|
+
</li>
|
23
|
+
</ul>
|
24
|
+
</div>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
.widget.widget-dashing-state {
|
2
|
+
|
3
|
+
.dashing-contrib {
|
4
|
+
&.state-warning {
|
5
|
+
background: rgba(247,206,27,0.5);
|
6
|
+
}
|
7
|
+
&.state-ok {
|
8
|
+
background: rgba(154,202,60,0.7);
|
9
|
+
}
|
10
|
+
&.state-critical {
|
11
|
+
background: rgba(195,32,38, 0.6);
|
12
|
+
}
|
13
|
+
}
|
14
|
+
.basic-stats {
|
15
|
+
|
16
|
+
font-size: 160px;
|
17
|
+
text-align: center;
|
18
|
+
|
19
|
+
.stats-item {
|
20
|
+
padding: 50px;
|
21
|
+
display: inline-block;
|
22
|
+
}
|
23
|
+
.stats-title {
|
24
|
+
font-size: 40px;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
ul {
|
29
|
+
padding: 10px 200px;
|
30
|
+
li {
|
31
|
+
display: inline-block;
|
32
|
+
padding: 10px 10px;
|
33
|
+
margin: 10px;
|
34
|
+
font-size: 25px;
|
35
|
+
&.item-state-ok {
|
36
|
+
background: rgba(154,202,60,1);
|
37
|
+
}
|
38
|
+
&.item-state-warning {
|
39
|
+
background: rgba(247,206,27,1);
|
40
|
+
}
|
41
|
+
&.item-state-critical {
|
42
|
+
background: rgba(195,32,38, 1);
|
43
|
+
}
|
44
|
+
border-radius: 10px;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
}
|
@@ -1,10 +1,12 @@
|
|
1
|
-
<
|
1
|
+
<div data-bind-class="state | prepend 'dashing-contrib state-'">
|
2
|
+
<h1 class="title" data-bind="title"></h1>
|
2
3
|
|
3
|
-
<ul>
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
</ul>
|
4
|
+
<ul>
|
5
|
+
<li data-foreach-metric="metrics">
|
6
|
+
<span data-bind-class="metric.label | prepend 'label '" class="label" data-bind="metric.label"></span>
|
7
|
+
<span class="value" data-bind="metric.value"></span>
|
8
|
+
</li>
|
9
|
+
</ul>
|
9
10
|
|
10
|
-
<p class="updated-at" data-bind="updatedAtMessage"></p>
|
11
|
+
<p class="updated-at" data-bind="updatedAtMessage"></p>
|
12
|
+
</div>
|
@@ -2,17 +2,19 @@
|
|
2
2
|
&.widget-kue-status {
|
3
3
|
background: #f0f0f0;
|
4
4
|
color: #636466;
|
5
|
-
}
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
ul {
|
7
|
+
margin: 0 15px;
|
8
|
+
text-align: left;
|
9
|
+
font-size: 22px;
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
li {
|
12
|
+
padding: 6px 0px;
|
13
|
+
.value {
|
14
|
+
float: right;
|
15
|
+
}
|
15
16
|
}
|
16
17
|
}
|
18
|
+
|
17
19
|
}
|
18
20
|
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class Dashing.NagiosList extends Dashing.Widget
|
2
|
+
@accessor 'hasCritical', ->
|
3
|
+
if (@get('critical').length > 0) then true else false
|
4
|
+
@accessor 'hasWarning', ->
|
5
|
+
if (@get('warning').length > 0) then true else false
|
6
|
+
|
7
|
+
@accessor 'criticalMap', ->
|
8
|
+
@_groupBy(@get('critical'))
|
9
|
+
|
10
|
+
@accessor 'warningMap', ->
|
11
|
+
@_groupBy(@get('warning'))
|
12
|
+
|
13
|
+
@accessor 'okMap', ->
|
14
|
+
@_groupBy(@get('ok'))
|
15
|
+
|
16
|
+
ready: ->
|
17
|
+
node = $(@node)
|
18
|
+
style = 'overflow': 'hidden'
|
19
|
+
node.parent().css(style)
|
20
|
+
|
21
|
+
clear: ->
|
22
|
+
|
23
|
+
|
24
|
+
_groupBy: (items) ->
|
25
|
+
maps = {}
|
26
|
+
for item, index in items
|
27
|
+
item.last_check = @_parseTime(item.last_check)
|
28
|
+
if !maps[item.host]
|
29
|
+
maps[item.host] = [item]
|
30
|
+
else
|
31
|
+
maps[item.host] = maps[item.host].concat item
|
32
|
+
|
33
|
+
results = []
|
34
|
+
for key, item of maps
|
35
|
+
node = host: key, checks: item
|
36
|
+
results = results.concat node
|
37
|
+
|
38
|
+
return results
|
39
|
+
|
40
|
+
_parseTime: (timestamp) ->
|
41
|
+
time = new Date(timestamp)
|
42
|
+
return "#{@_toTwoDigits(time.getHours())}:#{@_toTwoDigits(time.getMinutes())}"
|
43
|
+
|
44
|
+
_toTwoDigits: (val) ->
|
45
|
+
val = val + ''
|
46
|
+
if val.length == 1
|
47
|
+
return "0#{val}"
|
48
|
+
|
49
|
+
return val
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<h1 class="title" data-bind="title" data-showif="title"></h1>
|
2
|
+
|
3
|
+
<ul class="critical-list" data-showif="hasCritical">
|
4
|
+
<li data-foreach-item="criticalMap">
|
5
|
+
<span class="host-title" data-bind="item.host"></span>
|
6
|
+
<div class="checks-list">
|
7
|
+
<div class="check-item" data-foreach-check="item.checks">
|
8
|
+
<span class="check-item-name" data-bind="check.service"></span>
|
9
|
+
<span class="check-item-timestamp" data-bind="check.last_check"></span>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
</li>
|
13
|
+
</ul>
|
14
|
+
|
15
|
+
<ul class="warning-list" data-showif="hasWarning">
|
16
|
+
<li data-foreach-item="warningMap">
|
17
|
+
<span class="host-title" data-bind="item.host"></span>
|
18
|
+
<div class="checks-list">
|
19
|
+
<div class="check-item" data-foreach-check="item.checks">
|
20
|
+
<span class="check-item-name" data-bind="check.service"></span>
|
21
|
+
<span class="check-item-timestamp" data-bind="check.last_check"></span>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</li>
|
25
|
+
</ul>
|
26
|
+
|
27
|
+
<ul class="ok-list" >
|
28
|
+
<li data-foreach-item="okMap">
|
29
|
+
<span class="host-title" data-bind="item.host"></span>
|
30
|
+
<div class="checks-list">
|
31
|
+
<div class="check-item" data-foreach-check="item.checks">
|
32
|
+
<span class="check-item-name" data-bind="check.service"></span>
|
33
|
+
<span class="check-item-timestamp" data-bind="check.last_check"></span>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</li>
|
37
|
+
</ul>
|