flareboard 0.0.1

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +89 -0
  3. data/bin/flareboard +220 -0
  4. metadata +90 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0d2579b252fee593a40c48761c6ac965bab4b39e
4
+ data.tar.gz: a9673657a91d16531d9f40fa8555aefa8d6a7706
5
+ SHA512:
6
+ metadata.gz: d7032d8918a66d9ef8f63cee3fe859a8afb95b6034d1bc138ed0aa77b86410d0f2db1d69ae80d43e44855d98c820639e0ac82be51193de62db12186b5d3f5bc4
7
+ data.tar.gz: 5856f2bdf2487914646e2a3de877aa29f0bd32cd5458617438d9c0a66152c00236ed1826f360820563175483d06a38b2a665e4e523993f8c8a21dbb2a24b95d4
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ ##What is Flareboard?
2
+
3
+ Flareboard is the way to get your [CloudFlare](http://www.cloudflare.com) stats
4
+ to display in your [StatusBoard](http://www.panic.com/statusboard). It has been
5
+ designed to be very easy to install and use. It requires no third-party gems,
6
+ and can be run on any version of ruby from 1.8.7 to 2.1.1.
7
+
8
+ Add your credentials and sites to flareboard, and it will hit the CloudFlare API
9
+ to grab your stats and convert them into the JSON that Statusboard uses for
10
+ graphing. You can drop the resulting file into a dropbox folder or host it on a
11
+ web server. Unless you are paying for a CloudFlare Pro account, your stats will
12
+ only update every 24 hours, so it's no use running flareboard more often than
13
+ that.
14
+
15
+ **Note**: For compatibility with 1.8.7. you *will* have to install the JSON gem.
16
+ Also, you have my sympathies for having to use 1.8.7.
17
+
18
+ ## Installation
19
+
20
+ Copy the file ```bin/flareboard``` onto your computer. Put it either in a bin
21
+ directory in your path or somewhere else. If you are using ruby 1.8.7, then
22
+ you'll have to run ```sudo gem install json``` before it will work.
23
+
24
+ ## Configuration
25
+
26
+ There are three ways of configuring the script. Via the command-line arguments
27
+ documented in the previous section, via a config file (*~/.flareboard.rc*), or
28
+ by editing the script directly. In order of priority (highest to lowest), it
29
+ will use command-line options, the config file, and then the hard-coded config
30
+ hash in the script.
31
+
32
+ It is *highly* recommended to use a config file, as passing your API token on
33
+ the command-line is a security risk, and modifying the script itself will make
34
+ upgrades manual and laborious.
35
+
36
+ ### :title
37
+ The title that will show up on your status board
38
+
39
+ ### :token
40
+ Your Cloudflare token - available via their website at
41
+ https://www.cloudflare.com/my-account
42
+
43
+ ### :email
44
+ The email you have registered with cloudflare. **NOT** your username!
45
+
46
+ ### :interval
47
+ Interval Values - see https://www.cloudflare.com/docs/client-api.html for
48
+ latest.
49
+
50
+ 20-40 only update once a day - it is no use polling more often than that
51
+ 20 = Past 30 days
52
+ 30 = Past 7 days
53
+ 40 = Past day
54
+ !!! Anything higher than this requires a paid CloudFlare account !!!
55
+ !!! This also enables greater than daily updates !!!
56
+ 100 = 24 hours ago
57
+ 110 = 12 hours ago
58
+ 120 = 6 hours ago
59
+
60
+ ### :sites
61
+ Sites have a site specific title, a URL, and a color for the graph.
62
+ Colors: yellow, green, red, purple, blue, mediumGray, pink, aqua, orange, lightGray
63
+
64
+ Here is an example config file, using the same data as the example hash.
65
+
66
+ ---
67
+ :token: XXXXXXX
68
+ :email: user@example.com
69
+ :sites:
70
+ - :title: 'Should I Use That In Prod'
71
+ :url: 'shouldiusethatinprod.com'
72
+ :color: 'red'
73
+ - :title: "It's Not Rocket Science"
74
+ :url: 'itsnotrocketscience.info'
75
+ :color: 'purple'
76
+
77
+ ## Usage
78
+
79
+ Usage: flareboard [options]
80
+ -f, --file FILE Where to write the JSON output
81
+ Defaults to STDOUT
82
+ -t, --token TOKEN Your CloudFlare API token
83
+ -e, --email EMAIL Your CloudFlare email address
84
+ -i, --interval INTERVAL CloudFlare history interval
85
+ Defaults to 40
86
+ --title TITLE Title of the status board
87
+ Defaults to 'Cloudflare - Pageviews'
88
+
89
+ If no file is given, flareboard will write to standard out.
data/bin/flareboard ADDED
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env ruby
2
+ # @author David Bishop
3
+
4
+ require 'net/http'
5
+ if RUBY_VERSION < '1.9'
6
+ require 'net/https'
7
+ end
8
+ require 'json'
9
+ require 'optparse'
10
+ require 'yaml'
11
+
12
+ # Rather than dump out a free-form string, on errors dump out something that
13
+ # the status board app can read in and display
14
+ #
15
+ # @param error [String] Short description of the problem
16
+ # @param detail [String] Longer description or specific error code
17
+ # @return [nil]
18
+ def exit_json(error, detail)
19
+ # return the error in json form
20
+ sperror = {
21
+ 'error' => {
22
+ 'message' => error,
23
+ 'detail' => detail
24
+ }
25
+ }
26
+ STDERR.puts error, detail
27
+ puts sperror.to_json
28
+ exit 1
29
+ end
30
+
31
+ # Take the integer that CloudFlare uses and return a description in english
32
+ #
33
+ # @param interval [Integer] Integer needed by Cloudflare API
34
+ # @return [String] Description in english
35
+ def name_interval(interval)
36
+ title = {
37
+ 20 => 'Last Month',
38
+ 30 => 'Last Week',
39
+ 40 => 'Yesterday',
40
+ 100 => '24 Hours Ago',
41
+ 110 => '12 Hours Ago',
42
+ 120 => '6 Hours Ago'
43
+ }
44
+
45
+ # hash.fetch will return the second parameter if the key doesn't exist
46
+ title.fetch(interval, 'Invalid interval')
47
+ end
48
+
49
+ # ~~~~~ CONFIG BEGIN ~~~~~
50
+
51
+ options = {
52
+ :title => 'Cloudflare - Pageviews',
53
+ :token => 'XXXXXX',
54
+ :email => 'user@example.com',
55
+ :interval => 40,
56
+ :graph => 'bar',
57
+ :sites => [
58
+ { :title => 'Should I Use That In Prod',
59
+ :url => 'shouldiusethatinprod.com',
60
+ :color => 'red'
61
+ },
62
+ { :title => "It's Not Rocket Science",
63
+ :url => 'itsnotrocketscience.info',
64
+ :color => 'purple'
65
+ }
66
+ ]
67
+ }
68
+
69
+ # YOU SHOULD NOT NEED TO EDIT ANYTHING BELOW HERE
70
+ # IF YOU DO, PLEASE OPEN A BUG REPORT AT http://github.com/teancom/flareboard
71
+ # ~~~~~ CONFIG END ~~~~~
72
+
73
+ # The config file
74
+ CONFIG_FILE = File.join(ENV['HOME'], '.flareboard.rc')
75
+ if File.exist? CONFIG_FILE
76
+ config_options = YAML.load_file(CONFIG_FILE)
77
+ options.merge!(config_options)
78
+ end
79
+
80
+ # The name of this program
81
+ EXE_NAME = File.basename($PROGRAM_NAME)
82
+ # @todo Add support for graph type
83
+ option_parser = OptionParser.new do |opts|
84
+ opts.on('-f FILE',
85
+ '--file',
86
+ 'Where to write the JSON output',
87
+ 'Defaults to STDOUT'
88
+ ) do |file|
89
+ options[:file] = file
90
+ end
91
+ opts.on('-t TOKEN',
92
+ '--token',
93
+ 'Your CloudFlare API token'
94
+ ) do |token|
95
+ options[:token] = token
96
+ end
97
+ opts.on('-e EMAIL',
98
+ '--email',
99
+ 'Your CloudFlare email address'
100
+ ) do |email|
101
+ options[:email] = email
102
+ end
103
+ opts.on('-i INTERVAL',
104
+ '--interval',
105
+ Integer,
106
+ 'CloudFlare history interval',
107
+ 'Defaults to 40'
108
+ ) do |interval|
109
+ options[:interval] = interval
110
+ end
111
+ opts.on('--title TITLE',
112
+ 'Title of the status board',
113
+ "Defaults to 'Cloudflare - Pageviews'"
114
+ ) do |title|
115
+ options[:title] = title
116
+ end
117
+ # opts.on('--graph GRAPH',
118
+ # 'The type of graph - bar or line',
119
+ # 'Defaults to bar'
120
+ # ) do |graph|
121
+ # options[:graph] = graph
122
+ # end
123
+ opts.on("\n")
124
+ opts.on("If no file is given, #{EXE_NAME} will write to standard out.")
125
+ end
126
+
127
+ option_parser.parse!
128
+
129
+ if options.key? :file
130
+ path = File.expand_path(options[:file])
131
+ dir = File.dirname(path)
132
+ begin
133
+ $stdout.reopen(path, 'w')
134
+ rescue Errno::ENOENT
135
+ abort "Can't write into #{dir}. Does it exist?"
136
+ rescue Errno::EACCES
137
+ abort File.writable?(dir) ? "Can't write #{path}. No permission." : "Can't write into #{dir}. No permission."
138
+ rescue Errno::EISDIR
139
+ abort 'Please pass in a file name, not a directory name.'
140
+ rescue => e
141
+ abort e.message
142
+ end
143
+ end
144
+
145
+ # The graph hash needs to match the JSON object that StatusBoard requires
146
+ graph = {
147
+ 'graph' => {
148
+ 'title' => options[:title],
149
+ 'type' => options[:graph],
150
+ 'datasequences' => []
151
+ }
152
+ }
153
+
154
+ uri = URI.parse('https://www.cloudflare.com/api_json.html')
155
+ request = Net::HTTP::Post.new(uri.path)
156
+
157
+ options[:sites].each_with_index do | site, key |
158
+ request.set_form_data(
159
+ 'a' => 'stats',
160
+ 'tkn' => options[:token],
161
+ 'email' => options[:email],
162
+ 'z' => site[:url],
163
+ 'interval' => options[:interval]
164
+ )
165
+ httpreq = Net::HTTP.new(uri.host, uri.port)
166
+ httpreq.use_ssl = true
167
+ if RUBY_VERSION < '1.9'
168
+ httpreq.verify_mode = OpenSSL::SSL::VERIFY_NONE
169
+ end
170
+
171
+ response = httpreq.start do |http|
172
+ http.request(request)
173
+ end
174
+
175
+ # Got back something other than a 2xx response code
176
+ unless response.is_a? Net::HTTPSuccess
177
+ exit_json('Problems contacting the Cloudflare server', response.msg)
178
+ end
179
+
180
+ # Parse the JSON we got back from CloudFlare
181
+ begin
182
+ result = JSON.parse(response.body)
183
+ rescue UnparserError => e
184
+ exit_json('Unable to parse the Cloudflare JSON', e)
185
+ end
186
+
187
+ # Figure out what sort of error we got back
188
+ errcodes = { 'E_UNAUTH' => "Couldn't authenticate: ",
189
+ 'err_ts' => 'Invalid interval: ',
190
+ 'err_zone_not_found' => 'Probable typo in site name: ',
191
+ 'E_MAXAPI' => 'CloudFlare wants you to not hit them as much: ',
192
+ 'E_INVLDINPUT' => 'Unknown problem. Congrats! This is weird: '
193
+ }
194
+
195
+ if result['result'] == 'error'
196
+ if errcodes.key? result['err_code']
197
+ exit_json(errcodes[result['err_code']] + result['msg'],
198
+ result['err_code'])
199
+ else
200
+ exit_json("Unable to retrieve the Cloudflare JSON: #{result['msg']}",
201
+ result['err_code'])
202
+ end
203
+ end
204
+
205
+ totalhits = result['response']['result']['objs'][0]['requestsServed']['cloudflare']
206
+ crawlerhits = result['response']['result']['objs'][0]['trafficBreakdown']['pageviews']['crawler']
207
+
208
+ graph['graph']['datasequences'][key] = {
209
+ 'title' => site[:title],
210
+ 'color' => site[:color],
211
+ 'datapoints' => [{
212
+ 'title' => name_interval(options[:interval]),
213
+ 'value' => totalhits - crawlerhits
214
+ }]
215
+ }
216
+ # graph['graph']['datasequences'][key]['datapoints'][0]['title'] = 'Nudiustertian'
217
+ # graph['graph']['datasequences'][key]['datapoints'][1]['title'] = 'Yesterday'
218
+ end
219
+
220
+ puts graph.to_json
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flareboard
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - David Bishop
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.8'
55
+ description: |-
56
+ flareboard allows you to display your CloudFlare statistics
57
+ in the Panic Software's StatusBoard app
58
+ email: david at gnuconsulting dotcom
59
+ executables:
60
+ - flareboard
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - README.md
65
+ - bin/flareboard
66
+ homepage: http://github.com/teancom/flareboard
67
+ licenses:
68
+ - ISC
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project: flareboard
86
+ rubygems_version: 2.2.2
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: flareboard gets your cloudflare stats into statusboard
90
+ test_files: []