telemetry 1.0.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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in telemetry.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 W. Gersham Meharg
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Telemetry
2
+
3
+ This gem provides a wrapper around the Telemetry API (http://www.telemetryboard.com).
4
+
5
+ ## Installation
6
+
7
+ Install on your system:
8
+
9
+ $ gem install telemetry
10
+
11
+ ## Usage
12
+
13
+ Create a config file on your disk (by default /etc/telemetryd_config.rb). This file may have ruby code in it, you may include your own gems, etc. The file supports two configuration directives "interval" and "api_token". The interval is how frequently each flow block is executed with the results sent to the server. Please note if the result from a block is unchanged from the previous execution then it will be sent to the server only once per day.
14
+
15
+ For more details please see our website.
16
+
17
+ Example simple config:
18
+
19
+ interval 5
20
+ api_token "c65bc385a3b30135590a80973483ebf"
21
+
22
+ gauge "my-gauge" do
23
+ set value: 45
24
+ set max: 100
25
+ end
26
+
27
+ To start the daemon daemonized:
28
+
29
+ $ telemetryd.rb -d
30
+
31
+ To kill the daemon:
32
+
33
+ $ telemetryd.rb -k
34
+
35
+ Omitting the -d will start the process in the foreground and log to stdout. This is useful for debugging your config file.
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/telemetryd ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "dante"
4
+ require_relative "../lib/telemetry.rb"
5
+
6
+ include Telemetry
7
+
8
+ runner = Dante::Runner.new('telemetryd', :port => 9990)
9
+ runner.description = "telemetryd, a daemon for sending data to www.telemetryboard.com"
10
+ runner.with_options do |opts|
11
+ opts.on("-c", "--config PATH", String, "Config file location") do |config|
12
+ options[:config] = config
13
+ end
14
+ end
15
+
16
+ runner.execute do |opts|
17
+
18
+ # Load the Config File
19
+ config_file = opts[:config]
20
+ config_file ||= "/etc/telemetryd_config.rb"
21
+ config_file_path = File.absolute_path(config_file)
22
+ if File.exist?(config_file_path)
23
+ require_relative config_file_path
24
+ else
25
+ puts "Config file not found, please create /etc/telemetryd_config.rb or specify its location with -c"
26
+ exit
27
+ end
28
+
29
+ # Loop Forever
30
+ loop do
31
+ start_timestamp = Time.now.to_f
32
+ output = Telemetry.run_scheduled_flow_updates
33
+ Telemetry::Net.send(output)
34
+ Telemetry.wait_for_interval_from(start_timestamp)
35
+ end
36
+ end
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Telemetry
4
+
5
+ def token
6
+ @@token
7
+ end
8
+
9
+ def api_token(token)
10
+ @@token = token
11
+ end
12
+
13
+ def interval(interval)
14
+ @@interval = interval
15
+ end
16
+
17
+ # Ensure a minimum of 1 second between loops
18
+ def wait_for_interval_from(timestamp)
19
+ @@interval ||= 60
20
+ @@interval = 1.0 if @@interval < 1
21
+ sleep_length = timestamp + @@interval.to_f - Time.now.to_f
22
+ sleep sleep_length if sleep_length > 0
23
+ end
24
+
25
+ def set_json(x)
26
+ x.each {|k,v| @@h[k.to_sym] = MultiJson.load(v)}
27
+ end
28
+
29
+ def set(x)
30
+ x.each {|k,v| @@h[k.to_sym] = v}
31
+ end
32
+
33
+ def barchart(tag, frequency = 0, &block)
34
+ @@tasks ||= []
35
+ @@tasks << [ :barchart, tag, frequency, block ]
36
+ end
37
+
38
+ def countdown(tag, frequency = 0, &block)
39
+ @@tasks ||= []
40
+ @@tasks << [ :countdown, tag, frequency, block ]
41
+ end
42
+
43
+ def gauge(tag, frequency = 0, &block)
44
+ @@tasks ||= []
45
+ @@tasks << [ :gauge, tag, frequency, block ]
46
+ end
47
+
48
+ def graph(tag, frequency = 0, &block)
49
+ @@tasks ||= []
50
+ @@tasks << [ :graph, tag, frequency, block ]
51
+ end
52
+
53
+ def icon(tag, frequency = 0, &block)
54
+ @@tasks ||= []
55
+ @@tasks << [ :icon, tag, frequency, block ]
56
+ end
57
+
58
+ def iframe(tag, frequency = 0, &block)
59
+ @@tasks ||= []
60
+ @@tasks << [ :iframe, tag, frequency, block ]
61
+ end
62
+
63
+ def log(tag, frequency = 0, &block)
64
+ @@tasks ||= []
65
+ @@tasks << [ :log, tag, frequency, block ]
66
+ end
67
+
68
+ def map(tag, frequency = 0, &block)
69
+ @@tasks ||= []
70
+ @@tasks << [ :map, tag, frequency, block ]
71
+ end
72
+
73
+ def multigauge(tag, frequency = 0, &block)
74
+ @@tasks ||= []
75
+ @@tasks << [ :multigauge, tag, frequency, block ]
76
+ end
77
+
78
+ def servers(tag, frequency = 0, &block)
79
+ @@tasks ||= []
80
+ @@tasks << [ :servers, tag, frequency, block ]
81
+ end
82
+
83
+ def table(tag, frequency = 0, &block)
84
+ @@tasks ||= []
85
+ @@tasks << [ :table, tag, frequency, block ]
86
+ end
87
+
88
+ def text(tag, frequency = 0, &block)
89
+ @@tasks ||= []
90
+ @@tasks << [ :text, tag, frequency, block ]
91
+ end
92
+
93
+ def tickertape(tag, frequency = 0, &block)
94
+ @@tasks ||= []
95
+ @@tasks << [ :tickertape, tag, frequency, block ]
96
+ end
97
+
98
+ def timechart(tag, frequency = 0, &block)
99
+ @@tasks ||= []
100
+ @@tasks << [ :timechart, tag, frequency, block ]
101
+ end
102
+
103
+ def timeline(tag, frequency = 0, &block)
104
+ @@tasks ||= []
105
+ @@tasks << [ :timeline, tag, frequency, block ]
106
+ end
107
+
108
+ def timeseries(tag, frequency = 0, &block)
109
+ @@tasks ||= []
110
+ @@tasks << [ :timeseries, tag, frequency, block ]
111
+ end
112
+
113
+ def upstatus(tag, frequency = 0, &block)
114
+ @@tasks ||= []
115
+ @@tasks << [ :upstatus, tag, frequency, block ]
116
+ end
117
+
118
+ def value(tag, frequency = 0, &block)
119
+ @@tasks ||= []
120
+ @@tasks << [ :value, tag, frequency, block ]
121
+ end
122
+
123
+ def run_scheduled_flow_updates
124
+ @@buffer = {}
125
+ @@last_values ||= {}
126
+ @@values_expires_at ||= {}
127
+ @@next_run_at ||= {}
128
+
129
+ @@tasks.each do |task|
130
+ @@h = {}
131
+ variant, tag, frequency, block = task
132
+
133
+ # Check whether we should wait an interval before running
134
+ if frequency > 0
135
+ next if @@next_run_at[tag] && @@next_run_at[tag] <= Time.now.to_i
136
+ @@next_run_at[tag] = Time.now.to_i + frequency.to_i
137
+ end
138
+
139
+ # Execute the flow
140
+ block.yield
141
+
142
+ # Append the variant
143
+ values = @@h.merge({variant: variant})
144
+
145
+ # Skip if the values haven't changed (though send 1/day regardless)
146
+ if @@last_values[tag] != values || @@values_expires_at[tag] < Time.now.to_i
147
+ @@buffer[tag] = values
148
+ @@last_values[tag] = values # Save the value so we dont update unless it changes
149
+ @@values_expires_at[tag] = Time.now.to_i + 86400 # Force an update 1/day
150
+ end
151
+ end
152
+
153
+ @@buffer
154
+ end
155
+ end
156
+
@@ -0,0 +1,63 @@
1
+ #/usr/bin/env ruby
2
+
3
+ module Telemetry
4
+ class Net
5
+ require "multi_json"
6
+ require "rest_client"
7
+
8
+ def self.send(data)
9
+ return unless Telemetry.token
10
+ return unless data.size > 0
11
+
12
+ RestClient.proxy = ENV['http_proxy'] if ENV['http_proxy']
13
+
14
+ uri = "http://#{Telemetry.token}:@data.telemetryboard.com/v1/data.json"
15
+ body = MultiJson.dump({:data => data})
16
+
17
+ puts "#{Time.now} Updating Data (#{data.keys.join(", ")})"
18
+
19
+ begin
20
+ response = RestClient.post(uri, body, :content_type => :json, :accept => :json) do |response, request, result|
21
+ case response.code
22
+ when 200
23
+ json = MultiJson.load(response)
24
+ if json
25
+ puts "#{Time.now} Update OK: Updated #{json["updated"].count} flows (#{json["updated"].join(", ")})" if json["updated"] && json["updated"].count > 0
26
+ puts "#{Time.now} Update OK: Skipped #{json["skipped"].count} flows (#{json["skipped"].join(", ")})" if json["skipped"] && json["skipped"].count > 0
27
+ puts "#{Time.now} Update OK: Errors with #{json["errors"].count} flows (#{json["errors"].join(", ")})" if json["errors"] && json["errors"].count > 0
28
+ end
29
+ when 400
30
+ puts "#{Time.now} ERROR 400: Request error. #{response}. Exiting."
31
+ exit
32
+ when 401
33
+ puts "#{Time.now} ERROR 401: Authentication failed, please check your api_token. Exiting."
34
+ exit
35
+ when 403
36
+ puts "#{Time.now} ERROR 403: Authorization failed, please check your account access. Exiting."
37
+ exit
38
+ when 429
39
+ puts "#{Time.now} ERROR 429: Rate limited. Please reduce your update interval. Pausing updates for 300s."
40
+ sleep 300
41
+ when 500
42
+ puts "#{Time.now} ERROR 500: Data API server error. Pausing updates for 60s."
43
+ sleep 60
44
+ when 503
45
+ puts "#{Time.now} ERROR 503: Data API server is down. Pausing updates for 60s."
46
+ sleep 60
47
+ else
48
+ puts "#{Time.now} ERROR UNK: #{response}. Exiting."
49
+ exit
50
+ end
51
+ end
52
+
53
+ rescue Errno::ETIMEDOUT => e
54
+ puts "#{Time.now} ERROR #{e}"
55
+ sleep 60
56
+
57
+ rescue Errno::ECONNREFUSED => e
58
+ puts "#{Time.now} ERROR #{e}"
59
+ sleep 60
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module Telemetry
2
+ VERSION = "1.0.0"
3
+ end
data/lib/telemetry.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require_relative "telemetry/version"
5
+ require_relative "telemetry/telemetry"
6
+ require_relative "telemetry/config_parser"
data/telemetry.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'telemetry/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "telemetry"
8
+ gem.version = Telemetry::VERSION
9
+ gem.authors = ["W. Gersham Meharg"]
10
+ gem.email = ["gersham@etosi.com"]
11
+ gem.description = %q{Telemetry Data Submission API Gem. See our website for a more detailed description.}
12
+ gem.summary = %q{Telemetry Data Submission API Gem}
13
+ gem.homepage = "http://www.telemetryboard.com"
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+ gem.required_ruby_version = '>= 1.9.2'
19
+ gem.add_dependency "oj"
20
+ gem.add_dependency "multi_json"
21
+ gem.add_dependency "rest-client"
22
+ gem.add_dependency "dante"
23
+ end
@@ -0,0 +1,16 @@
1
+ interval 5
2
+ api_token "c65bc385a3b301359590a80973483ebf"
3
+
4
+ gauge "demo-gauge" do
5
+ set value: rand(1000)
6
+ set max: rand(1000)
7
+ end
8
+
9
+ gauge "blah-gauge" do
10
+ set value: 44
11
+ set max: 55
12
+ end
13
+
14
+ value "foobard" do
15
+ set value: rand(1000)
16
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: telemetry
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - W. Gersham Meharg
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: oj
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: multi_json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rest-client
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: dante
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Telemetry Data Submission API Gem. See our website for a more detailed
79
+ description.
80
+ email:
81
+ - gersham@etosi.com
82
+ executables:
83
+ - telemetryd
84
+ extensions: []
85
+ extra_rdoc_files: []
86
+ files:
87
+ - .gitignore
88
+ - Gemfile
89
+ - LICENSE.txt
90
+ - README.md
91
+ - Rakefile
92
+ - bin/telemetryd
93
+ - lib/telemetry.rb
94
+ - lib/telemetry/config_parser.rb
95
+ - lib/telemetry/telemetry.rb
96
+ - lib/telemetry/version.rb
97
+ - telemetry.gemspec
98
+ - telemetryd_config.rb
99
+ homepage: http://www.telemetryboard.com
100
+ licenses: []
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: 1.9.2
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.24
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: Telemetry Data Submission API Gem
123
+ test_files: []