Skip to content

Instantly share code, notes, and snippets.

@dav3860
Last active August 2, 2016 14:48
Show Gist options
  • Save dav3860/14b29b70afa589c0b94d to your computer and use it in GitHub Desktop.
Save dav3860/14b29b70afa589c0b94d to your computer and use it in GitHub Desktop.
<script type='text/javascript'>
$(function() {
Dashing.cycleDashboards({timeInSeconds: 30, stagger: true});
});
</script>
<% content_for :title do %>Zabbix<% end %>
<% settings.screens.each do |screen| %>
<div class="gridster">
<ul>
<li data-row="1" data-col="1" data-sizex="2" data-sizey="1">
<div data-id="<%=screen%>_text" data-view="Text" style="background-color:#3299CC;"></div>
</li>
<li data-row="2" data-col="1" data-sizex="1" data-sizey="2">
<div data-id="<%=screen%>_warn" data-view="Zabbix" data-title="warning" style="background-color:#96bf48;"></div>
</li>
<li data-row="2" data-col="2" data-sizex="1" data-sizey="2">
<div data-id="<%=screen%>_avrg" data-view="Zabbix" data-title="average" style="background-color:#96bf48;"></div>
</li>
<li data-row="4" data-col="1" data-sizex="1" data-sizey="2">
<div data-id="<%=screen%>_high" data-view="Zabbix" data-title="high" style="background-color:#96bf48;"></div>
</li>
<li data-row="4" data-col="2" data-sizex="1" data-sizey="2">
<div data-id="<%=screen%>_disa" data-view="Zabbix" data-title="disaster" style="background-color:#96bf48;"></div>
</li>
<li data-row="1" data-col="4" data-sizex="2" data-sizey="5">
<div data-id="<%=screen%>_list" data-view="ZabbixList" data-title="Last active triggers" style="background-color:#444;"></div>
</li>
</ul>
</div>
<% end %>
source 'https://rubygems.org'
gem 'dashing'
gem 'activesupport'
gem 'zabby'
gem 'therubyracer', :platforms => :ruby
class Dashing.Text extends Dashing.Widget
onData: (data) ->
if data.status
# clear existing "status-*" classes
$(@get('node')).attr 'class', (i,c) ->
c.replace /\bstatus-\S+/g, ''
# add new class
$(@get('node')).addClass "status-#{data.status}"
<h1 class="title" data-bind="title"></h1>
<h3 data-bind="text"></h3>
<p class="more-info" data-bind="moreinfo"></p>
<p class="updated-at" data-bind="updatedAtMessage"></p>
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #3299CC;
$background-disa-color-1: #E82711;
$background-disa-color-2: #9B2D23;
$text-disa-color: #fff;
@-webkit-keyframes status-disa-background {
0% { background-color: $background-disa-color-1; }
50% { background-color: $background-disa-color-2; }
100% { background-color: $background-disa-color-1; }
}
@mixin animation($animation-name, $duration, $function, $animation-iteration-count:""){
-webkit-animation: $animation-name $duration $function #{$animation-iteration-count};
-moz-animation: $animation-name $duration $function #{$animation-iteration-count};
-ms-animation: $animation-name $duration $function #{$animation-iteration-count};
}
$title-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.7);
// ----------------------------------------------------------------------------
// Widget-text styles
// ----------------------------------------------------------------------------
.widget-text {
background-color: $background-color;
.title {
font-size: 48px;
color: $title-color;
}
.more-info {
color: $moreinfo-color;
}
.updated-at {
color: rgba(255, 255, 255, 0.7);
}
&.large h3 {
font-size: 65px;
}
}
.widget.status-disa-blink {
color: $text-disa-color;
background-color: $background-disa-color-1;
@include animation(status-disa-background, 2s, ease, infinite);
}
.widget.status-ok {
background-color:#3299CC
}
Dashing.on 'ready', ->
# Dashing.debugMode = true
class Dashing.Zabbix extends Dashing.Widget
@accessor 'current', Dashing.AnimatedValue
@accessor 'difference', ->
if @get('last')
last = parseInt(@get('last'))
current = parseInt(@get('current'))
if last != 0
diff = Math.abs(Math.round((current - last) / last * 100))
"#{diff}%"
else
""
@accessor 'arrow', ->
if @get('last')
if parseInt(@get('current')) > parseInt(@get('last')) then 'icon-arrow-up'
else if parseInt(@get('current')) < parseInt(@get('last')) then 'icon-arrow-down'
else ''
onData: (data) ->
if data.status
# clear existing "status-*" classes
$(@get('node')).attr 'class', (i,c) ->
c.replace /\bstatus-\S+/g, ''
# add new class
$(@get('node')).addClass "status-#{data.status}"
<h1 class="title" data-bind="title"></h1>
<h2 class="value" data-bind="current | shortenedNumber | prepend prefix | append suffix"></h2>
<p class="change-rate">
<i data-bind-class="arrow"></i>
</p>
<!--
<ul>
<li data-foreach-item="items">
<span class="descr" data-bind="item | truncate 50"></span>
</li>
</ul>
<p class="more-info" data-bind="moreinfo | raw"></p>
<p class="updated-at" data-bind="updatedAtMessage"></p>
require 'zabby'
require 'json'
require 'active_support/core_ext/numeric/time'
########################## CONSTANTS ##############################
SERVER = "http://zabbixserver"
USER = "apiuser"
PASSWORD = "apipassword"
MINPRIORITY = 2
ANIMATE = 5.minutes
# Defines which Zabbix groups will be displays in which screen :
SCREENS = {
"Screen 1" => [ "Virtual machines", "Networking"],
"Screen 2" => [ "Windows servers" ],
}
NAMES = {
1 => "info",
2 => "warn",
3 => "avrg",
4 => "high",
5 => "disa"
}
NAMES.default = "ok"
############################ MAIN ##################################
lastchange = Time.now
set :screens, SCREENS.keys # Pass the list of screens to HTML page
# Initialize the last count hash
lastcount = {}
SCREENS.each do | k, v |
lastcount[k] = {}
for i in MINPRIORITY..5
lastcount[k][i] = 0
end
end
# Start the scheduler
SCHEDULER.every '15s', allow_overlapping: false do
begin
serv = Zabby.init do
set :server => SERVER
set :user => USER
set :password => PASSWORD
login
end
SCREENS.each do |screen, groups|
# Query Zabbix for current problem triggers
result = serv.run {
Zabby::Trigger.get(
"filter" => {"value" => 1 },
"min_severity" => MINPRIORITY,
"groupids" => serv.run {Zabby::Hostgroup.get("filter" =>{"name" => groups},"preservekeys" => 0)}.keys(),
"output" => "extend",
"monitored" => 1,
"withLastEventUnacknowledged" => 1,
"skipDependent" => 1,
"expandData" => "host",
"expandDescription" => 1,
"sortfield" => "lastchange",
"sortorder" => "DESC")
}
triggers = {
0 => [],
1 => [],
2 => [],
3 => [],
4 => [],
5 => []
}
lastchange = {
0 => 0,
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0
}
triggerlist = []
# Parse the results
jsonObj = JSON.parse(result.to_json)
jsonObj.each do |j|
prio = j["priority"].to_i
last = j["lastchange"].to_i
tgrid = j["triggerid"]
tlink = SERVER + "/events.php?triggerid=" + tgrid + "&period=604800"
hostnme = j["hostname"]
hostnme = hostnme.gsub(/\..*$/, '') # strip domain name if necessary
descr = j["description"]
triggers[prio] << hostnme + " : " + descr
status = Time.at(last) < (Time.now - ANIMATE) ? NAMES[prio] : NAMES[prio] + "-blink"
triggerlist << {
host: hostnme,
trigger: descr,
link: tlink,
widget_class: "#{status}"
}
if last > lastchange[prio] then
lastchange[prio] = last
end
end
triggerlist = triggerlist.take(15) # Limit the list to 15 entries
# Loop through priorities to populate the widgets
for i in MINPRIORITY..5
total = triggers[i].count
#delta = total - lastcount[screen][i]
#if delta != 0 then
# lastchange = Time.now
#end
# Set the color of the widget
if total > 0 then
#status = (delta == 0 and Time.at(lastchange[i]) < (Time.now - ANIMATE)) ? NAMES[i] : NAMES[i] + "-blink"
status = Time.at(lastchange[i]) < (Time.now - ANIMATE) ? NAMES[i] : NAMES[i] + "-blink"
else
status = "ok" end
# Limit the displayed events to 3 per widget
list = triggers[i].uniq
if list.count > 4 then
list = list[0..2]
list << "[...]"
end
# send the data to the widget
send_event( screen + "_" + NAMES[i], { current: total, last: lastcount[screen][i], status: status, items: list } )
lastcount[screen][i] = total # Copy trigger counts to last value
end
send_event( screen + "_list", { items: triggerlist } )
send_event( screen + "_text", {title: screen, status: "ok"} )
end
rescue
SCREENS.each do |screen, groups|
send_event( screen + "_text", {title: "DASHBOARD IN ERROR", status: NAMES[5] + "-blink"} )
end
end
end
/*
//=require_directory .
//=require_tree ../../widgets
*/
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #222;
$text-color: #fff;
$background-avrg-color-1: #A0522D;
$background-avrg-color-2: #FFA07A;
$text-avrg-color: #fff;
$background-warn-color-1: #FFD117;
$background-warn-color-2: #FF9618;
$text-warn-color: #fff;
$background-high-color-1: #CD5C5C;
$background-high-color-2: #FF9999;
$text-high-color: #fff;
$background-disa-color-1: #E82711;
$background-disa-color-2: #9B2D23;
$text-disa-color: #fff;
@-webkit-keyframes status-warn-background {
0% { background-color: $background-warn-color-2; }
50% { background-color: $background-warn-color-1; }
100% { background-color: $background-warn-color-2; }
}
@-webkit-keyframes status-warn-background-still {
0% { background-color: $background-warn-color-2; }
50% { background-color: $background-warn-color-2; }
100% { background-color: $background-warn-color-2; }
}
@-webkit-keyframes status-avrg-background {
0% { background-color: $background-avrg-color-1; }
50% { background-color: $background-avrg-color-2; }
100% { background-color: $background-avrg-color-1; }
}
@-webkit-keyframes status-avrg-background-still {
0% { background-color: $background-avrg-color-1; }
50% { background-color: $background-avrg-color-1; }
100% { background-color: $background-avrg-color-1; }
}
@-webkit-keyframes status-high-background {
0% { background-color: $background-high-color-1; }
50% { background-color: $background-high-color-2; }
100% { background-color: $background-high-color-1; }
}
@-webkit-keyframes status-high-background-still {
0% { background-color: $background-high-color-1; }
50% { background-color: $background-high-color-1; }
100% { background-color: $background-high-color-1; }
}
@-webkit-keyframes status-disa-background {
0% { background-color: $background-disa-color-1; }
50% { background-color: $background-disa-color-2; }
100% { background-color: $background-disa-color-1; }
}
@-webkit-keyframes status-disa-background-still {
0% { background-color: $background-disa-color-1; }
50% { background-color: $background-disa-color-1; }
100% { background-color: $background-disa-color-1; }
}
@mixin animation($animation-name, $duration, $function, $animation-iteration-count:""){
-webkit-animation: $animation-name $duration $function #{$animation-iteration-count};
-moz-animation: $animation-name $duration $function #{$animation-iteration-count};
-ms-animation: $animation-name $duration $function #{$animation-iteration-count};
}
// ----------------------------------------------------------------------------
// Base styles
// ----------------------------------------------------------------------------
html {
font-size: 100%;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
body {
margin: 0;
background-color: $background-color;
font-size: 20px;
color: $text-color;
font-family: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif;
}
b, strong {
font-weight: bold;
}
a {
text-decoration: none;
color: inherit;
}
img {
border: 0;
-ms-interpolation-mode: bicubic;
vertical-align: middle;
}
img, object {
max-width: 100%;
}
iframe {
max-width: 100%;
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
td {
vertical-align: middle;
}
ul, ol {
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, p {
padding: 0;
margin: 0;
}
h1 {
margin-bottom: 12px;
text-align: center;
font-size: 30px;
font-weight: 400;
}
h2 {
text-transform: uppercase;
font-size: 76px;
font-weight: 700;
color: $text-color;
}
h3 {
font-size: 25px;
font-weight: 600;
color: $text-color;
}
// ----------------------------------------------------------------------------
// Base widget styles
// ----------------------------------------------------------------------------
.gridster {
margin: 0px auto;
}
.icon-background {
width: 100%!important;
height: 100%;
position: absolute;
left: 0;
top: 0;
opacity: 0.1;
font-size: 275px;
}
.list-nostyle {
list-style: none;
}
.gridster ul {
list-style: none;
}
.gs_w {
width: 100%;
display: table;
cursor: pointer;
}
.widget {
padding: 25px 12px;
text-align: center;
width: 100%;
display: table-cell;
vertical-align: middle;
font-size: 28px;
}
.widget.status-avrg {
color: $text-avrg-color;
background-color: $background-avrg-color-1;
@include animation(status-avrg-background-still, 2s, ease, infinite);
.icon-avrg-sign {
display: inline-block;
}
.title, .more-info {
color: $text-avrg-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.widget.status-avrg-blink {
color: $text-avrg-color;
background-color: $background-avrg-color-1;
@include animation(status-avrg-background, 2s, ease, infinite);
.icon-avrg-sign {
display: inline-block;
}
.title, .more-info {
color: $text-avrg-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.widget.status-warn {
color: $text-warn-color;
background-color: $background-warn-color-1;
@include animation(status-warn-background-still, 2s, ease, infinite);
.icon-warn-sign {
display: inline-block;
}
.title, .more-info {
color: $text-warn-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.widget.status-warn-blink {
color: $text-warn-color;
background-color: $background-warn-color-1;
@include animation(status-warn-background, 2s, ease, infinite);
.icon-warn-sign {
display: inline-block;
}
.title, .more-info {
color: $text-warn-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.widget.status-high {
color: $text-high-color;
background-color: $background-high-color-1;
@include animation(status-high-background-still, 2s, ease, infinite);
.icon-high-sign {
display: inline-block;
}
.title, .more-info {
color: $text-high-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.widget.status-high-blink {
color: $text-high-color;
background-color: $background-high-color-1;
@include animation(status-high-background, 2s, ease, infinite);
.icon-high-sign {
display: inline-block;
}
.title, .more-info {
color: $text-high-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.widget.status-disa {
color: $text-disa-color;
background-color: $background-disa-color-1;
@include animation(status-disa-background-still, 2s, ease, infinite);
.icon-disa-sign {
display: inline-block;
}
.title, .more-info {
color: $text-disa-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.widget.status-disa-blink {
color: $text-disa-color;
background-color: $background-disa-color-1;
@include animation(status-disa-background, 2s, ease, infinite);
.icon-disa-sign {
display: inline-block;
}
.title, .more-info {
color: $text-disa-color;
}
.descr {
font-size: 28px;
color: $text-avrg-color;
}
}
.more-info {
font-size: 15px;
position: absolute;
bottom: 32px;
left: 0;
right: 0;
}
.updated-at {
font-size: 15px;
position: absolute;
bottom: 12px;
left: 0;
right: 0;
}
#save-gridster {
display: none;
position: fixed;
top: 0;
margin: 0px auto;
left: 50%;
z-index: 1000;
background: black;
width: 190px;
text-align: center;
border: 1px solid white;
border-top: 0px;
margin-left: -95px;
padding: 15px;
}
#save-gridster:hover {
padding-top: 25px;
}
#saving-instructions {
display: none;
padding: 10px;
width: 500px;
height: 122px;
z-index: 1000;
background: white;
top: 100px;
color: black;
font-size: 15px;
padding-bottom: 4px;
textarea {
white-space: nowrap;
width: 494px;
height: 80px;
}
}
#lean_overlay {
position: fixed;
z-index:100;
top: 0px;
left: 0px;
height:100%;
width:100%;
background: #000;
display: none;
}
#container {
padding-top: 5px;
}
// ----------------------------------------------------------------------------
// Clearfix
// ----------------------------------------------------------------------------
.clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; overflow: hidden; }
.clearfix:after { clear: both; }
.clearfix { zoom: 1; }
Dashing.on 'ready', ->
# Dashing.debugMode = true
class Dashing.ZabbixList extends Dashing.Widget
<h1 class="title" data-bind="title"></h1>
<ul class="items list-nostyle">
<li class="item" data-foreach-item="items" data-bind-class="item.widget_class">
<a data-bind-href="item.link">
<span class="label host" data-bind="item.host"></span>
<span class="label trigger" data-bind="item.trigger | truncate 33"></span>
<div class="clearfix" />
</a>
</li>
</ul>
$value-color: #FFF;
$background-color: #222;
$text-color: #fff;
$background-avrg-color-1: #A0522D;
$background-avrg-color-2: #FFA07A;
$text-avrg-color: #fff;
$background-warn-color-1: #FFD117;
$background-warn-color-2: #FF9618;
$text-warn-color: #fff;
$background-high-color-1: #CD5C5C;
$background-high-color-2: #FF9999;
$text-high-color: #fff;
$background-disa-color-1: #E82711;
$background-disa-color-2: #9B2D23;
$text-disa-color: #fff;
@-webkit-keyframes status-warn-background {
0% { background-color: $background-warn-color-2; }
50% { background-color: $background-warn-color-1; }
100% { background-color: $background-warn-color-2; }
}
@-webkit-keyframes status-warn-background-still {
0% { background-color: $background-warn-color-2; }
50% { background-color: $background-warn-color-2; }
100% { background-color: $background-warn-color-2; }
}
@-webkit-keyframes status-avrg-background {
0% { background-color: $background-avrg-color-1; }
50% { background-color: $background-avrg-color-2; }
100% { background-color: $background-avrg-color-1; }
}
@-webkit-keyframes status-avrg-background-still {
0% { background-color: $background-avrg-color-1; }
50% { background-color: $background-avrg-color-1; }
100% { background-color: $background-avrg-color-1; }
}
@-webkit-keyframes status-high-background {
0% { background-color: $background-high-color-1; }
50% { background-color: $background-high-color-2; }
100% { background-color: $background-high-color-1; }
}
@-webkit-keyframes status-high-background-still {
0% { background-color: $background-high-color-1; }
50% { background-color: $background-high-color-1; }
100% { background-color: $background-high-color-1; }
}
@-webkit-keyframes status-disa-background {
0% { background-color: $background-disa-color-1; }
50% { background-color: $background-disa-color-2; }
100% { background-color: $background-disa-color-1; }
}
@-webkit-keyframes status-disa-background-still {
0% { background-color: $background-disa-color-1; }
50% { background-color: $background-disa-color-1; }
100% { background-color: $background-disa-color-1; }
}
@mixin animation($animation-name, $duration, $function, $animation-iteration-count:""){
-webkit-animation: $animation-name $duration $function #{$animation-iteration-count};
-moz-animation: $animation-name $duration $function #{$animation-iteration-count};
-ms-animation: $animation-name $duration $function #{$animation-iteration-count};
}
$title-color: rgba(255, 255, 255, 1);
$label-color: rgba(255, 255, 255, 0.7);
.widget.widget-zabbix-list{
background-color: $background-color;
padding: 0px;
vertical-align: top;
img.background {
width: 100% !important;
position: absolute;
left: 0;
top: 30px;
opacity: 0.05;
}
.title {
color: $title-color;
}
ol, ul {
margin: 0px;
text-align: left;
color: $label-color;
}
ol {
list-style-position: inside;
}
li {
margin-bottom: 5px;
}
.list-nostyle {
}
.items{
list-style: none;
li {
margin-top: 5px;
&.avrg-blink {
background-color: $background-avrg-color-1;
@include animation(status-avrg-background, 2s, ease, infinite);
}
&.warn-blink {
background-color: $background-warn-color-1;
@include animation(status-warn-background, 2s, ease, infinite);
}
&.high-blink {
background-color: $background-high-color-1;
@include animation(status-high-background, 2s, ease, infinite);
}
&.disa-blink {
background-color: $background-disa-color-1;
@include animation(status-disa-background, 2s, ease, infinite);
}
&.avrg {
background-color: $background-avrg-color-1;
@include animation(status-avrg-background-still, 2s, ease, infinite);
}
&.warn {
background-color: $background-warn-color-1;
@include animation(status-warn-background-still, 2s, ease, infinite);
}
&.high {
background-color: $background-high-color-1;
@include animation(status-high-background-still, 2s, ease, infinite);
}
&.disa {
background-color: $background-disa-color-1;
@include animation(status-disa-background-still, 2s, ease, infinite);
}
.label {
display: block;
color: $label-color;
font-size: 40px;
word-wrap: break-word;
&.host {
float: left;
text-align: left;
padding: 5px 0px 5px 10px;
}
&.trigger {
float: left;
text-align: left;
padding-top: 10px;
font-size: 34px;
padding: 11px 0px 5px 5px;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment