ifttt-gdash 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZGU3ZjlhYTQ1ZGVkOTlhMTgwZGVjNzU2MzZkNmFjNGYzN2ViMTY0Yw==
5
- data.tar.gz: !binary |-
6
- NjczNGNiZGYyNTY2NzZmOWJmMWZjN2FiZDVkNTdiNmI5ZThmZWM0MA==
2
+ SHA1:
3
+ metadata.gz: a905ac9bf55f0dcf3f1e033d6f994592f453578f
4
+ data.tar.gz: 668819d176f3a2e3ac0a0971d73bc7bfa1839ad3
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MDNmNjgyNjNjNWIyZjRjMTYzMzg1YmFkNDQ1YjM4NDZlYzA2YTFkNjBiNTQ0
10
- OGFiNzczOTUxOGMxNzI5MDM0YzljMjM5YzJiZWY3NTI5YWJhMzQzMTgwZmE4
11
- MWQ3NTg2MzViNDViNDMzMDIwZGY0NTJmMTExMGQ5YjBkOWI2NjE=
12
- data.tar.gz: !binary |-
13
- OGIyZGRkYjc2MDNmMDViYjkzYjZhMjY5ZjQ1MjRhZDA0MGYxZmVhMzJhOThk
14
- ZGI0YjU3YzBiOTFhZmY4MTk2ZjJlYjQ1NzI2OGIwZmNlNDU0Y2Y2NzQxZWVl
15
- MTYzNmIwZmRlOWIzMjgwNTQwNmYxNWQxNjU3NjQ0MGRkYmZkNTM=
6
+ metadata.gz: b3924408b437fcadd12d50a1900266fb002e18177285b9690162dc2bf2dd55a257f315e1a73764411fa435d7ae0625d458ba82226c0f4f67af1f277a698cd478
7
+ data.tar.gz: 21a0514bb3ccfa2c553cf73fa1f9dcd67af640935865b6fec76bde7e5734f856a237fa1266b1b6b1ffc0064e4170f3df1e01d89bf205bae9e547f49a3820d73d
data/lib/gdash.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'sinatra/base'
3
+ require 'yaml'
4
+ require 'erb'
5
+ require 'redcarpet'
6
+
7
+ class GDash
8
+ require 'gdash/dashboard'
9
+ require 'gdash/monkey_patches'
10
+ require 'gdash/sinatra_app'
11
+ require 'graphite_graph'
12
+
13
+ attr_reader :graphite_base, :graphite_render, :dash_templates, :height, :width, :from, :until
14
+
15
+ def initialize(graphite_base, render_url, dash_templates, options={})
16
+ @graphite_base = graphite_base
17
+ @graphite_render = [@graphite_base, "/render/"].join
18
+ @dash_templates = dash_templates
19
+ @height = options.delete(:height)
20
+ @width = options.delete(:width)
21
+ @from = options.delete(:from)
22
+ @until = options.delete(:until)
23
+
24
+ raise "Dashboard templates directory #{@dash_templates} does not exist" unless File.directory?(@dash_templates)
25
+ end
26
+
27
+ def dashboard(name, options={})
28
+ options[:width] ||= @width
29
+ options[:height] ||= @height
30
+ options[:from] ||= @from
31
+ options[:until] ||= @until
32
+
33
+ Dashboard.new(name, dash_templates, options)
34
+ end
35
+
36
+ def list
37
+ dashboards.map {|dash| dash[:link]}
38
+ end
39
+
40
+ def dashboards
41
+ dashboards = []
42
+
43
+ Dir.entries(dash_templates).each do |dash|
44
+ begin
45
+ yaml_file = File.join(dash_templates, dash, "dash.yaml")
46
+ if File.exist?(yaml_file)
47
+ dashboards << YAML.load_file(yaml_file).merge({:link => dash})
48
+ end
49
+ rescue Exception => e
50
+ p e
51
+ end
52
+ end
53
+
54
+ dashboards.sort_by{|d| d[:name].to_s}
55
+ end
56
+ end
@@ -0,0 +1,52 @@
1
+ class GDash
2
+ class Dashboard
3
+ attr_accessor :properties
4
+
5
+ def initialize(short_name, dir, options={})
6
+ raise "Cannot find dashboard directory #{dir}" unless File.directory?(dir)
7
+
8
+ @properties = {:graph_width => nil,
9
+ :graph_height => nil,
10
+ :graph_from => nil,
11
+ :graph_until => nil}
12
+
13
+ @properties[:short_name] = short_name
14
+ @properties[:directory] = File.join(dir, short_name)
15
+ @properties[:yaml] = File.join(dir, short_name, "dash.yaml")
16
+
17
+ raise "Cannot find YAML file #{yaml}" unless File.exist?(yaml)
18
+
19
+ @properties.merge!(YAML.load_file(yaml))
20
+
21
+ # Properties defined in dashboard config file are overridden when given on initialization
22
+ @properties[:graph_width] = options.delete(:width) || graph_width
23
+ @properties[:graph_height] = options.delete(:height) || graph_height
24
+ @properties[:graph_from] = options.delete(:from) || graph_from
25
+ @properties[:graph_until] = options.delete(:until) || graph_until
26
+ @properties[:options] = options
27
+ end
28
+
29
+ def graphs(options={})
30
+ options[:width] ||= graph_width
31
+ options[:height] ||= graph_height
32
+ options[:from] ||= graph_from
33
+ options[:until] ||= graph_until
34
+
35
+ graphs = Dir.entries(directory).select{|f| f.match(/\.graph$/)}
36
+
37
+ overrides = options.reject { |k,v| v.nil? }
38
+
39
+ graphs.sort.map do |graph|
40
+ {:name => File.basename(graph, ".graph"), :graphite => GraphiteGraph.new(File.join(directory, graph), overrides)}
41
+ end
42
+ end
43
+
44
+ def method_missing(method, *args)
45
+ if properties.include?(method)
46
+ properties[method]
47
+ else
48
+ super
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,37 @@
1
+ class Array
2
+ def in_groups_of(chunk_size, padded_with=nil)
3
+ if chunk_size <= 1
4
+ if block_given?
5
+ self.each{|a| yield([a])}
6
+ else
7
+ self
8
+ end
9
+ else
10
+ arr = self.clone
11
+
12
+ # how many to add
13
+ padding = chunk_size - (arr.size % chunk_size)
14
+ padding = 0 if padding == chunk_size
15
+
16
+ # pad at the end
17
+ arr.concat([padded_with] * padding)
18
+
19
+ # how many chunks we'll make
20
+ count = arr.size / chunk_size
21
+
22
+ # make that many arrays
23
+ result = []
24
+ count.times {|s| result << arr[s * chunk_size, chunk_size]}
25
+
26
+ if block_given?
27
+ result.each{|a| yield(a)}
28
+ else
29
+ result
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ class GraphiteGraph
36
+ attr_accessor :properties, :file
37
+ end
@@ -0,0 +1,202 @@
1
+ class GDash
2
+ class SinatraApp < ::Sinatra::Base
3
+ def initialize(graphite_base, graph_templates, options = {})
4
+ # where the whisper data is
5
+ @whisper_dir = options.delete(:whisper_dir) || "/var/lib/carbon/whisper"
6
+
7
+ # where graphite lives
8
+ @graphite_base = graphite_base
9
+
10
+ # where the graphite renderer is
11
+ @graphite_render = [@graphite_base, "/render/"].join
12
+
13
+ # where to find graph, dash etc templates
14
+ @graph_templates = graph_templates
15
+
16
+ # the dash site might have a prefix for its css etc
17
+ @prefix = options.delete(:prefix) || ""
18
+
19
+ # the page refresh rate
20
+ @refresh_rate = options.delete(:refresh_rate) || 60
21
+
22
+ # how many columns of graphs do you want on a page
23
+ @graph_columns = options.delete(:graph_columns) || 2
24
+
25
+ # how wide each graph should be
26
+ @graph_width = options.delete(:graph_width)
27
+
28
+ # how hight each graph sould be
29
+ @graph_height = options.delete(:graph_height)
30
+
31
+ # Dashboard title
32
+ @dash_title = options.delete(:title) || "Graphite Dashboard"
33
+
34
+ # Time filters in interface
35
+ @interval_filters = options.delete(:interval_filters) || Array.new
36
+
37
+ @intervals = options.delete(:intervals) || []
38
+
39
+ @top_level = Hash.new
40
+ Dir.entries(@graph_templates).each do |category|
41
+ if File.directory?("#{@graph_templates}/#{category}")
42
+ unless ("#{category}" =~ /^\./ )
43
+ @top_level["#{category}"] = GDash.new(@graphite_base, "/render/", File.join(@graph_templates, "/#{category}"), {:width => @graph_width, :height => @graph_height})
44
+ end
45
+ end
46
+ end
47
+
48
+ super()
49
+ end
50
+
51
+ set :static, true
52
+ set :views, File.join(File.expand_path(File.dirname(__FILE__)), "../..", "views")
53
+ if Sinatra.const_defined?("VERSION") && Gem::Version.new(Sinatra::VERSION) >= Gem::Version.new("1.3.0")
54
+ set :public_folder, File.join(File.expand_path(File.dirname(__FILE__)), "../..", "public")
55
+ else
56
+ set :public, File.join(File.expand_path(File.dirname(__FILE__)), "../..", "public")
57
+ end
58
+
59
+ get '/' do
60
+ if @top_level.empty?
61
+ @error = "No dashboards found in the templates directory"
62
+ end
63
+
64
+ erb :index
65
+ end
66
+
67
+ get '/:category/:dash/details/:name' do
68
+ options = query_params.except(:from, :until)
69
+ if @top_level["#{params[:category]}"].list.include?(params[:dash])
70
+ @dashboard = @top_level[@params[:category]].dashboard(params[:dash], options)
71
+ else
72
+ @error = "No dashboard called #{params[:dash]} found in #{params[:category]}/#{@top_level[params[:category]].list.join ','}."
73
+ end
74
+
75
+ if @intervals.empty?
76
+ @error = "No intervals defined in configuration"
77
+ end
78
+
79
+ if main_graph = @dashboard.graphs[params[:name].to_i][:graphite]
80
+ @graphs = @intervals.map do |e|
81
+ new_props = {:from => e[0], :title => "#{main_graph.properties[:title]} - #{e[1]}"}
82
+ new_props = main_graph.properties.merge new_props
83
+ GraphiteGraph.new(main_graph.file, new_props)
84
+ end
85
+ else
86
+ @error = "No such graph available"
87
+ end
88
+
89
+ erb :detailed_dashboard
90
+ end
91
+
92
+ get '/:category/:dash/full/?*' do
93
+ options = {}
94
+ params["splat"] = params["splat"].first.split("/")
95
+
96
+ params["columns"] = params["splat"][0].to_i || @graph_columns
97
+
98
+ if params["splat"].size == 3
99
+ options[:width] = params["splat"][1].to_i
100
+ options[:height] = params["splat"][2].to_i
101
+ else
102
+ options[:width] = @graph_width
103
+ options[:height] = @graph_height
104
+ end
105
+
106
+ options.merge!(query_params)
107
+
108
+ if @top_level["#{params[:category]}"].list.include?(params[:dash])
109
+ @dashboard = @top_level[@params[:category]].dashboard(params[:dash], options)
110
+ else
111
+ @error = "No dashboard called #{params[:dash]} found in #{params[:category]}/#{@top_level[params[:category]].list.join ','}"
112
+ end
113
+
114
+ erb :full_size_dashboard, :layout => false
115
+ end
116
+
117
+ get '/:category/:dash/?*' do
118
+ options = {}
119
+ params["splat"] = params["splat"].first.split("/")
120
+
121
+ case params["splat"][0]
122
+ when 'time'
123
+ options[:from] = params["splat"][1] || "-1hour"
124
+ options[:until] = params["splat"][2] || "now"
125
+ end
126
+
127
+ options.merge!(query_params)
128
+
129
+ if @top_level["#{params[:category]}"].list.include?(params[:dash])
130
+ @dashboard = @top_level[@params[:category]].dashboard(params[:dash], options)
131
+ else
132
+ @error = "No dashboard called #{params[:dash]} found in #{params[:category]}/#{@top_level[params[:category]].list.join ','}."
133
+ end
134
+
135
+ erb :dashboard
136
+ end
137
+
138
+ get '/docs/' do
139
+ markdown :README, :layout_engine => :erb
140
+ end
141
+
142
+ helpers do
143
+ include Rack::Utils
144
+
145
+ alias_method :h, :escape_html
146
+
147
+ def current_top_level
148
+ @top_level[@params[:category]]
149
+ end
150
+
151
+ def query_params
152
+ hash = {}
153
+ protected_keys = [:category, :dash, :splat]
154
+
155
+ params.each do |k, v|
156
+ hash[k.to_sym] = v unless protected_keys.include?(k.to_sym)
157
+ end
158
+
159
+ hash
160
+ end
161
+
162
+ def uri_to_dashboard(dash, options = {})
163
+ category = options[:category] || params[:category]
164
+ if options[:from]
165
+ uri = URI([@prefix, category, dash, 'time', h(options[:from]), h(options[:to])].join('/'))
166
+ else
167
+ uri = URI([@prefix, category, dash].join('/'))
168
+ end
169
+ query = request.query_string.empty? ? {} : Rack::Utils.parse_nested_query(request.query_string)
170
+ query.merge!((options[:query] || {}).stringify_keys)
171
+ uri.query = query.to_query unless query.empty?
172
+ uri.to_s
173
+ end
174
+
175
+ def uri_to_interval(options)
176
+ uri = URI([@prefix, params[:category], params[:dash], 'time', h(options[:from]), h(options[:to])].join('/'))
177
+ uri.query = request.query_string unless request.query_string.empty?
178
+ uri.to_s
179
+ end
180
+
181
+ def link_to_interval(options)
182
+ "<a href=\"#{ uri_to_interval(options) }\">#{ h(options[:label]) }</a>"
183
+ end
184
+
185
+ def uri_to_details(index)
186
+ uri = URI([@prefix, params[:category], @params[:dash], 'details', index].join('/'))
187
+ uri.query = request.query_string unless request.query_string.empty?
188
+ uri.to_s
189
+ end
190
+
191
+ # To be overriden by base classes, should they so desire.
192
+ # @dashboard holds the dashboard
193
+ def dashboard_preheader; ''; end
194
+ def dashboard_header; ''; end
195
+ def graph_caption(graph); ''; end
196
+ end
197
+
198
+ before do
199
+ content_type :html, 'charset' => 'utf-8'
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,104 @@
1
+ /* ==========================================================
2
+ * bootstrap-alerts.js v1.3.0
3
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
4
+ * ==========================================================
5
+ * Copyright 2011 Twitter, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ * ========================================================== */
19
+
20
+
21
+ !function( $ ){
22
+
23
+ /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
24
+ * ======================================================= */
25
+
26
+ var transitionEnd
27
+
28
+ $(document).ready(function () {
29
+
30
+ $.support.transition = (function () {
31
+ var thisBody = document.body || document.documentElement
32
+ , thisStyle = thisBody.style
33
+ , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
34
+ return support
35
+ })()
36
+
37
+ // set CSS transition event type
38
+ if ( $.support.transition ) {
39
+ transitionEnd = "TransitionEnd"
40
+ if ( $.browser.webkit ) {
41
+ transitionEnd = "webkitTransitionEnd"
42
+ } else if ( $.browser.mozilla ) {
43
+ transitionEnd = "transitionend"
44
+ } else if ( $.browser.opera ) {
45
+ transitionEnd = "oTransitionEnd"
46
+ }
47
+ }
48
+
49
+ })
50
+
51
+ /* ALERT CLASS DEFINITION
52
+ * ====================== */
53
+
54
+ var Alert = function ( content, selector ) {
55
+ this.$element = $(content)
56
+ .delegate(selector || '.close', 'click', this.close)
57
+ }
58
+
59
+ Alert.prototype = {
60
+
61
+ close: function (e) {
62
+ var $element = $(this).parent('.alert-message')
63
+
64
+ e && e.preventDefault()
65
+ $element.removeClass('in')
66
+
67
+ function removeElement () {
68
+ $element.remove()
69
+ }
70
+
71
+ $.support.transition && $element.hasClass('fade') ?
72
+ $element.bind(transitionEnd, removeElement) :
73
+ removeElement()
74
+ }
75
+
76
+ }
77
+
78
+
79
+ /* ALERT PLUGIN DEFINITION
80
+ * ======================= */
81
+
82
+ $.fn.alert = function ( options ) {
83
+
84
+ if ( options === true ) {
85
+ return this.data('alert')
86
+ }
87
+
88
+ return this.each(function () {
89
+ var $this = $(this)
90
+
91
+ if ( typeof options == 'string' ) {
92
+ return $this.data('alert')[options]()
93
+ }
94
+
95
+ $(this).data('alert', new Alert( this ))
96
+
97
+ })
98
+ }
99
+
100
+ $(document).ready(function () {
101
+ new Alert($('body'), '.alert-message[data-alert] .close')
102
+ })
103
+
104
+ }( window.jQuery || window.ender );