Schlagwort-Archive: Dashboard

[dashing] Willkommen Firma xyz über den gesamten Bildschirm

Das dashing.io Dashboard kann unter anderem in Empfangsbereichen von Firmen eingesetzt werden. Steht nun zum Beispiel ein Besuch eines Kunden an, so könnte man Ihn auf dem Dashboard willkommen heißen. Damit die Willkommensnachricht nicht nur unscheinbar in einer Kachel erscheint, habe ich dieses Widget erstellt. Die job Datei(rb) prüft ob es einen zeitlich passenden Eintrag in der csv Datei gibt und setzt das Widget per css auf Display Block. Das Widget legt sich über den gesamten Bildschirm, ist die Zeit des hinterlegten Kundenbesuchs abgelaufen so wird das Widget wieder ausgeblendet.

Folgende Dateien müssen in einem Verzeichnis Namens overlay abgelegt werden

overlay.coffee
class Dashing.Overlay extends Dashing.Widget
constructor: ->
super
onData: (data) ->
schalter = @schalter
node = $(@node)
if schalter == false then node.css(‚display‘,’none‘) else node.css(‚display‘,’block‘)
ready: ->
@onData(null)

overlay.html
<span data-bind=“titel“></span>
<div class=“bild“ ><img data-bind-src=“kunde“ ></div>
<div class=“text“ data-bind=“text | raw“></div>

overlay.scss
// —————————————————————————-
// Sass declarations
// —————————————————————————-
$background-color: #ec663c;
$title-color: rgba(255, 255, 255, 0.7);
$moreinfo-color:rgba(255, 255, 255, 0.7);
// —————————————————————————-
// Widget-text styles
// —————————————————————————-
.widget-overlay {
position: fixed;
bottom: 1px;
z-index:1000;
width:100%;
height:95%;
background-color: $background-color;
.title {
color: $title-color;
}
.more-info {
color: $moreinfo-color;
}
.updated-at {
color: rgba(255, 255, 255, 0.7);
}
.text{
color:#ffffff;
font-weight:bold;
margin-top:20%;
}
.bild{
height:100px;
width:95%;
text-align:right;
}
&.large h3 {
font-size: 65px;
}
}

Die rb Datei muss unter dem Verzeichnis jobs abgelegt werden, natürlich muss der Pfad zur CSV Datei angepasst werden.
overlay.rb
require ‚csv‘
require ‚json‘
require ‚date‘
require ‚time‘
ENV[‚TZ‘] = ‚Europe/Berlin‘
schalter = false
kunde = „x“
text = „x“
SCHEDULER.every ’30s‘ do
zeit = Time.now.to_i
schalter_zaehler = 0
ausgabe = {}
idx = 0
CSV.foreach(‚/home/dashing/sweet_dashboard_project/jobs/overlay.csv‘, col_sep: ‚;‘) do |row|
start = Time.parse(„#{row[0]} #{row[1]}:00 „).to_i
stop = Time.parse(„#{row[0]} #{row[2]}:00 „).to_i
if zeit.between?(start, stop)
schalter_zaehler += 1
kunde = row[3]
text = row[4]
ausgabe[0] = {:kunde => row[3],:text => row[4]}
end
end
if schalter_zaehler == 1
schalter = true
else
schalter = false
end
send_event(„overlay“,{ kunde: kunde , text: text, schalter: schalter })
#puts JSON.pretty_generate(ausgabe)
end

Aufbau der overlay.csv
2017-01-02;10:00;12:00;/assets/logo.png;Moin zusammen;
2017-05-08;20:00;21:51;/assets/logo.png;Willkommen Firma Kassupke<br/>bei der Tagung;

Die Logos der Firmen müssen unter dem Verzeichnis assets/images abgelegt werden.

Die Einbindung des Widgets erfolgt in der erb Datei in der letzten Zeile wie folgt:
<div data-id=“overlay“ data-view=“Overlay“ ></div>

Hier kann alles heruntergeladen werden.

[dashing] Icinga Widget ohne Soft-Zustände

In dem Artikel hatte ich ein Widget für dashing.io erstellt, welches die Icinga Alarme per json abholt und entsprechend ausgibt. In dem erstellten Job wurden jedoch auch die Soft-Zustände ausgegeben, was je nach System für Hektik sorgen kann.

Der Job wurde nun angepasst und mit Hilfe des Wertes service_attempt werden nun keine Soft-Zustände mehr ausgegeben.

attempt = werte[idx]["service_attempt"].split('/')
if attempt[0] == attempt[1]
if werte[idx]["service_state"].to_i == 0
dalert = "OK"
end
if werte[idx]["service_state"].to_i == 1
dalert = "WARNING"
z_warning += 1
end
if werte[idx]["service_state"].to_i == 2
dalert = "CRITICAL"
z_critical += 1
end
if werte[idx]["service_state"].to_i == 3
dalert = "UNKNOWN"
z_unknown += 1
end
laenge += 1
if laenge.to_i <= 20
review_content[laenge] = {:host => werte[idx][„host_name“],:what => werte[idx][„service_description“],:alert => dalert}
end
end

[dashing] Fehler beim auslesen einer Excel Datei

Beim auslesen von xlsx Dateien mit Hilfe von roo kam es zu keinen Problem, wenn die rb Datei direkt über die Kommandozeile ausgeführt wurde. Wurde die Datei jedoch innerhalb des Jobs Ordners abgelegt und über dashing ausgeführt, kam es zu folgendem Fehler:

.gem/ruby/gems/backports-3.6.6/lib/backports/std_lib.rb:9:in `require': cannot load such file -- roo (LoadError)
from /home/dashing/.gem/ruby/gems/backports-3.6.6/lib/backports/std_lib.rb:9:in `require_with_backports'
from /home/dashing/sweet_dashboard_project/jobs/todo.rb:1:in `'
from /home/dashing/.gem/ruby/gems/backports-3.6.6/lib/backports/std_lib.rb:9:in `require'
from /home/dashing/.gem/ruby/gems/backports-3.6.6/lib/backports/std_lib.rb:9:in `require_with_backports'
from /home/dashing/.gem/ruby/gems/dashing-1.3.4/lib/dashing/app.rb:157:in `block in require_glob'
from /home/dashing/.gem/ruby/gems/dashing-1.3.4/lib/dashing/app.rb:156:in `each'
from /home/dashing/.gem/ruby/gems/dashing-1.3.4/lib/dashing/app.rb:156:in `require_glob'
from /home/dashing/.gem/ruby/gems/dashing-1.3.4/lib/dashing/app.rb:167:in `'
from /home/dashing/.gem/ruby/gems/dashing-1.3.4/lib/dashing.rb:3:in `require'
from /home/dashing/.gem/ruby/gems/dashing-1.3.4/lib/dashing.rb:3:in `'

Das Problem trat nicht mehr auf, nachdem im Gemfile gem 'roo', '~> 2.3.2' hinterlegt wurde.

[dashing] Rss Widget

Ein Dashboard könnte auch in einem Empfangsbereich einer Firma genutzt werden. Neben aktuellen Informationen wie eventuell Zahlen der Firma können andere Informationesquellen wie Wetter oder Nachrichten eingebunden werden.
In diesem Fall habe ich ein kleines rss Widget erstellt, welches den Heise rss Feeds inklusive dem Artikelbild ausgibt.

rss.coffee
class Dashing.Rss extends Dashing.Widget

# constructor: ->
# super
onData: (data) ->
node = $(@node)
node.addClass("blinking")
setTimeout ( =>
node.removeClass("blinking")
), 5000

rss.html
<h1 class="title" data-bind="title"></h1>

<div  data-bind="titel" class="titel"></div>
<div class="bild">
<img  data-bind-src="bild" align="left">
</div>
<div class="beschreibung">
<span   data-bind="beschreibung | raw"></span>
</div>
<div style="clear:both"></div>
<p class="more-info" data-bind="moreinfo"></p>
<p class="updated-at" data-bind="updatedAtMessage"></p>

rss.scss
.widget-rss {
background-color: $background-color;
}
.more-info {
color: $moreinfo-color;
}
.updated-at {
color: rgba(255, 255, 255, 0.7);
}
li {
font-size: 15px;
margin-top: 8px;
text-indent: 10px;
font-weight: normal;
}
.title {
color: $title-color;
}
.beschreibung {
font-size:25px;
width:450px;
float:left;
text-align:left;
}
.bild {
float:left;
width:270px;
}
&.blinking {
animation: blink 1s linear infinite;
animation-iteration-count: 1;
}
}


job

require 'nokogiri'
require 'open-uri'
require 'xpath'
require 'split'
require 'sub'

SCHEDULER.every '10m', :first_in => 0 do |job|

@doc = Nokogiri::HTML(open("http://www.heise.de/newsticker/heise-atom.xml"))

beschreibung = @doc.xpath('//entry//summary')
titel = @doc.xpath('//entry//title')
bild = @doc.xpath('//entry//img')
bild = @doc.xpath('//entry//img')
zaehler = 1
while zaehler < titel.length
#puts titel[zaehler]
bil = bild[zaehler].to_s.sub("<img src=\"", "").split('"')[0]
tit = titel[zaehler].to_s.sub("<title type=\"text\">", "").to_s.sub("</title>", "")
besch =  beschreibung[zaehler].to_s.sub("<summary type=\"html\">", "").to_s.sub("</summary>", "")
send_event("heise",{ titel: tit , beschreibung: besch, bild: bil })
sleep 30
zaehler += 1
end
end

[dashing] Informationen aus dem Icinga auf dem Dashboard

Neben den bisher genannten Möglichkeiten können auch Informationen per http aus anderen Systemen wie in diesem Beispiel Icinga geholt und dargestellt werden. Für das Abrufen der Daten wird hier nicht die Api verwendet, sondern der http Aufruf mit entsprechendem Parameter um ein Json Array zu erhalten.
Für den Zugriff auf die Icinga Daten wurde auf dem gleichen System ein weiteres Icinga-web2 angelegt. Der in der Konfiguratin hinterlegte Benutzer für den Datenbankzugriff, hat in diesem Fall nur lesende Rechte.

Damit die Authentifizierung über htpasswd und nicht über die Datenbank erfolgt, wurde die config/authentication.ini wie folgt angepasst:

[autologin]

backend = external

Neben der erwähnten Datei muss ebenfalls die vhost Konfig für den icingaweb2 angepasst werden.
DirectoryIndex error_norewrite.html
ErrorDocument 404 /error_norewrite.html
</IfModule>
AuthType Basic
AuthName "Icinga Web 2"
AuthUserFile /etc/icingaweb2/icingaweb.htpasswd
Require valid-user
</Directory>

Die benötigte Passworddatei wird mit htpasswd -c icingaweb.htpasswd dashing erstellt.

Dashboard

Die Dateien für das Widget werden unter dem Widgetsverzeichniss icinga abgelegt, die rb Datei in dem Verzeichniss job. Innerhalb der rb Datei muss die Url zum Icinga inklusive der Benutzerdaten angepasst werden. Die Url kann so konfiguriert werden, das zum Beispiel nur Alarme einer bestimmten Hostgruppe dargestellt werden.

icinga.coffee
class Dashing.Icinga extends Dashing.Widget
onData: (data) ->
if data.blink
node = $(@node)
node.addClass(„blinking“)
setTimeout ( =>
node.removeClass(„blinking“)
), 5000

icinga.scss

// —————————————————————————-
// Sass declarations
// —————————————————————————-
@keyframes blink {
50% { opacity : 0.0; }
}

$background-color: rgba(135, 135, 135, 0.7);
$title-color: rgba(255, 255, 255, 0.7);
$in-color: rgba(255, 255, 255, 1.0);
$out-color: rgba(175, 175, 175, 1.0);
$updated-at-color: rgba(255, 255, 255, 0.7);

.widget-icinga {
background-color: $background-color;

.content {
text-align: left;
padding-top:25px;
vertical-align: top;
}

.title {
color: $title-color;
position: absolute;
top: 18px;
left: 0;
right: 0;
}

.updated-at {
color: $updated-at-color;
}

&.large h3 {
font-size: 45px;
}

li {
font-size: 15px;
margin-top: 8px;
text-indent: 10px;
font-weight: normal;
}

.host {
font-weight: bold;
width:50%;
float:left;
}

.CRITICAL {
font-weight:bold;
float:left;
text-align:right;
width:50%;
color:#ff0022;
}

.OK {
font-weight:bold;
float:left;
text-align:right;
width:50%;
color:#3bdb22;
}

.WARNING {
font-weight:bold;
float:left;
text-align:right;
width:50%;
color:#ffde00;
}

.UNKNOWN {
font-weight:bold;
float:left;
text-align:right;
width:50%;
color:#ffffff;
}

.what {
font-style:italic;
font-size:10px;
font-weight: normal;
}

&.blinking {
animation: blink 1s linear infinite;
animation-iteration-count: 2;
}
}

icinga.html
<h1 class=“title“ data-bind=“title“></h1>
<div class=“content“>
<ul>
<li data-foreach-value=“values“ data-bind-class=“value.status“>
<i data-bind-class=“value.icon“></i>
<span class=“host“ data-bind=“value.host“></span>
<span data-bind-class=“value.alert“ data-bind=“value.alert“></span>
<span class=“what“ data-bind=“value.what“></span>
</li>
</ul>
</div>
<p class=“updated-at“ data-bind=“updatedAtMessage“></p>

icinga.rb

# job um werte aus dem Icinga zu holen

require ’net/http‘
require ‚uri‘
require ‚json‘
require „addressable/uri“

review_content_hash = 0
SCHEDULER.every ’30s‘ do
#service status
uri = Addressable::URI.parse(„http://localhost/icingaweb2/monitoring/list/services?(hostgroup=web1|host=miranda)&service_state!=0&service_unhandled=1&sort=service_severity&format=json“)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
request.basic_auth(„dashing“, „passwd“)
response = http.request(request)
#host status
uriH = Addressable::URI.parse(„http://localhost/icingaweb2/monitoring/list/hosts?(hostgroup=web1|host=miranda)&host_state!=0&sort=service_severity&format=json“)
httpH = Net::HTTP.new(uriH.host, uriH.port)
requestH = Net::HTTP::Get.new(uriH.request_uri)
requestH.basic_auth(„dashing“, „passwd“)
responseH = httpH.request(requestH)
werteH = JSON.parse(responseH.body)

review_content = {}

# Liste der Hosts erstellen
hosts = []
werteH.length.times do |idx|
if werteH[idx][„host_state“].to_i != 0
dalert = „DOWN“
end

review_content[idx] = {:host => werteH[idx][„host_name“],:alert => dalert}
#Host der liste hinzufügen
hosts.push(werteH[idx][„host_name“])
end

laenge = review_content.length

werte = JSON.parse(response.body)

werte.length.times do |idx|

# wenn es keine hostdown Meldung gibt dann wird der Servicealarm ausgegeben
if hosts.include?(werte[idx][„host_name“]) == false

if werte[idx][„service_state“].to_i == 0
dalert = „OK“
end

if werte[idx][„service_state“].to_i == 1
dalert = „WARNING“
end

if werte[idx][„service_state“].to_i == 2
dalert = „CRITICAL“
end

if werte[idx][„service_state“].to_i == 3
dalert = „UNKNOWN“
end
laenge += 1
review_content[laenge] = {:host => werte[idx][„host_name“],:what => werte[idx][„service_description“],:alert => dalert}
end
end

if review_content_hash == review_content.to_set.hash
send_event(„icappl“,{ values: review_content.values })
else
send_event(„icappl“,{ values: review_content.values, blink: review_content.length })
end
review_content_hash = review_content.to_set.hash

# ende scheduler
end

 

dashing-icinga