telemetry 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|