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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +43 -0
- data/Rakefile +1 -0
- data/bin/telemetryd +36 -0
- data/lib/telemetry/config_parser.rb +156 -0
- data/lib/telemetry/telemetry.rb +63 -0
- data/lib/telemetry/version.rb +3 -0
- data/lib/telemetry.rb +6 -0
- data/telemetry.gemspec +23 -0
- data/telemetryd_config.rb +16 -0
- metadata +123 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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
|
data/lib/telemetry.rb
ADDED
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: []
|