opentsdb-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +62 -0
- data/lib/cloudinsight/opentsdb/client.rb +46 -0
- data/lib/cloudinsight/opentsdb/http_client.rb +38 -0
- data/lib/cloudinsight/opentsdb/query_param.rb +65 -0
- data/lib/cloudinsight/opentsdb/query_parser.rb +80 -0
- data/lib/cloudinsight/opentsdb/version.rb +5 -0
- data/lib/cloudinsight/opentsdb.rb +39 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2ebb5075958cfa76233980e4dae55bd0ad30e28e
|
4
|
+
data.tar.gz: 003174b10051ea7d851344a17ca254a31136d9d3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 827664beb3f3aaea2c5a2e010940738214bec02afdba5532629eaf9747bd418668a7f6e8655192fa607914320906d1d330315501c8cfa889b907b879befd5a46
|
7
|
+
data.tar.gz: 51b7fd589fa67d8490133476336a3e11070d0798062da5588d3a41fee5a38dabbffb0fca6b93734de1cdcee0f9878fd449ebacb6a6c53ba02a918563b2597ab5
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# opentsdb-ruby
|
2
|
+
|
3
|
+
Ruby client for OpenTSDB HTTP Query API.
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/cloudinsight/opentsdb-ruby.png)](https://travis-ci.org/cloudinsight/opentsdb-ruby) [![Code Climate](https://codeclimate.com/github/cloudinsight/opentsdb-ruby/badges/gpa.svg)](https://codeclimate.com/github/cloudinsight/opentsdb-ruby)
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'openstd-ruby', github: 'cloudinsight/opentsdb-ruby'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install openstd-ruby
|
21
|
+
|
22
|
+
|
23
|
+
## Quick Start Guide
|
24
|
+
|
25
|
+
### Configure openstdb
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
#config/initializers/cloudinsight_openstdb.rb
|
29
|
+
|
30
|
+
if defined?(CloudInsight)
|
31
|
+
CloudInsight::Opentsdb.configure do |config|
|
32
|
+
config.host = 'localhost' # opentsdb server host default: localhost
|
33
|
+
config.port = 4242 # opentsdb server port default: 4242
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
```
|
38
|
+
|
39
|
+
### Usage
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
|
43
|
+
# define simple query params
|
44
|
+
params = { begin: Time.now.ago(1.hour), q: 'avg:system.load.1{host=*}' }
|
45
|
+
# opensted
|
46
|
+
client = CloudInsight::Opentsdb::Client.new(params)
|
47
|
+
result = client.query # opentsdb json result
|
48
|
+
|
49
|
+
|
50
|
+
# complicate query params
|
51
|
+
params = { begin: Time.now.ago(1.hour), end: Time.now, q: 'avg:system.load.1{host=server1, host=server2, tagk=tagv}by{host}', interval: 360 }
|
52
|
+
client = CloudInsight::Opentsdb::Client.new(params)
|
53
|
+
result = client.query # opentsdb json result
|
54
|
+
|
55
|
+
|
56
|
+
# reconfig opentsdb host port
|
57
|
+
params = { host: '192.168.0.100', port: 8000, q: 'avg:system.load.1{host=*}' }
|
58
|
+
client = CloudInsight::Opentsdb::Client.new(params)
|
59
|
+
result = client.query # opentsdb json result
|
60
|
+
```
|
61
|
+
|
62
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'http_client'
|
2
|
+
module CloudInsight
|
3
|
+
module Opentsdb
|
4
|
+
# ruby client for OpenTsdb HTTP API
|
5
|
+
class Client
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_instance_delegators :@http, :post
|
9
|
+
|
10
|
+
attr_reader :host, :port, :query_options
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@host = options.delete(:host) || Opentsdb.host
|
14
|
+
@port = options.delete(:port) || Opentsdb.port
|
15
|
+
@http = HttpClient.new
|
16
|
+
@query_options = options
|
17
|
+
end
|
18
|
+
|
19
|
+
def query
|
20
|
+
[].tap do |data|
|
21
|
+
parse_queries.each do |query_commad|
|
22
|
+
data << post(query_uri, query_commad.to_json)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_queries
|
28
|
+
[].tap do |qs|
|
29
|
+
query_options[:q].split(';').each do |q|
|
30
|
+
query = QueryParser.parse(q)
|
31
|
+
query.interval = query_options[:interval]
|
32
|
+
query.start_time = query_options[:begin].to_i
|
33
|
+
query.end_time = query_options[:end].to_i
|
34
|
+
qs << query
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def query_uri
|
42
|
+
URI("http://#{host}:#{port}/api/query")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'benchmark'
|
3
|
+
module CloudInsight
|
4
|
+
module Opentsdb
|
5
|
+
# :nodoc:
|
6
|
+
class HttpClient
|
7
|
+
def post(uri, body)
|
8
|
+
send_http(uri) do |http|
|
9
|
+
Opentsdb.logger.debug "Http post body: #{body}"
|
10
|
+
req = Net::HTTP::Post.new(uri, headers)
|
11
|
+
req.body = body
|
12
|
+
http.request(req)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def headers
|
19
|
+
{ 'Content-Type' => 'application/json; charset=UTF-8' }
|
20
|
+
end
|
21
|
+
|
22
|
+
def send_http(uri)
|
23
|
+
Opentsdb.logger.info "Http request uri: #{uri}"
|
24
|
+
http = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https')
|
25
|
+
res = nil
|
26
|
+
time = Benchmark.realtime do
|
27
|
+
res = yield(http)
|
28
|
+
end
|
29
|
+
Opentsdb.logger.info "Response: #{res.code} consume: #{time} s"
|
30
|
+
res
|
31
|
+
rescue Timeout::Error, Errno::ECONNRESET, Net::HTTPBadResponse,
|
32
|
+
Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
33
|
+
Opentsdb.logger.error "Http request error: #{e}"
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module CloudInsight
|
2
|
+
# :nodoc:
|
3
|
+
class QueryParam
|
4
|
+
attr_accessor :aggregator, :rate, :metric, :tags, :downsample, :interval
|
5
|
+
attr_accessor :start_time, :end_time, :queries
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@aggregator = options[:aggregator]
|
9
|
+
@rate = options[:rate] || false
|
10
|
+
@metric = options[:metric]
|
11
|
+
@tags = options[:tags] || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def start_time
|
15
|
+
@start_time > 0 ? to_ms(@start_time) : (end_time - 3_600_000) # 1 hour ago
|
16
|
+
end
|
17
|
+
|
18
|
+
def end_time
|
19
|
+
@end_time > 0 ? to_ms(@end_time) : to_ms(Time.now)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json
|
23
|
+
{}.tap do |h|
|
24
|
+
h[:start] = start_time
|
25
|
+
h[:end] = end_time
|
26
|
+
h[:queries] = queries
|
27
|
+
end.to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
def tags
|
31
|
+
@tags.each do |tagk, tagv|
|
32
|
+
@tags[tagk] = tagv.to_a.compact.join('|') if tagv.is_a?(Array) || tagv.is_a?(Set)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def downsample
|
37
|
+
"#{interval}s-#{aggregator_for}" if interval
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def to_ms(time = Time.now)
|
43
|
+
(time.to_f * 1000).to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
def queries
|
47
|
+
[{}.tap do |qh|
|
48
|
+
qh[:aggregator] = aggregator
|
49
|
+
qh[:rate] = rate
|
50
|
+
qh[:metric] = metric
|
51
|
+
qh[:tags] = tags
|
52
|
+
qh[:downsample] = downsample if downsample
|
53
|
+
end]
|
54
|
+
end
|
55
|
+
|
56
|
+
def aggregator_for
|
57
|
+
case aggregator
|
58
|
+
when 'sum', 'avg' then 'avg'
|
59
|
+
when 'min' then 'mimmin'
|
60
|
+
when 'max' then 'mimmax'
|
61
|
+
else 'avg'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module CloudInsight
|
2
|
+
module Opentsdb
|
3
|
+
# :nodoc:
|
4
|
+
class QueryParser
|
5
|
+
class << self
|
6
|
+
def parse(q_string)
|
7
|
+
parts = split_for(q_string, ':')
|
8
|
+
return nil if parts.size < 2 || parts.size > 3
|
9
|
+
metric_query = {}
|
10
|
+
metric_query[:aggregator] = parts[0]
|
11
|
+
metric_query[:rate] = false
|
12
|
+
temp = parts[1]
|
13
|
+
if parts.size == 3
|
14
|
+
metric_query[:rate] = true if temp.start_with?('rate')
|
15
|
+
temp = parts[2]
|
16
|
+
end
|
17
|
+
query_metric = parse_query_metric(temp)
|
18
|
+
QueryParam.new metric_query.merge(query_metric)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def parse_query_metric(metric)
|
24
|
+
start_index = metric.index('{')
|
25
|
+
return { metric: metric } unless start_index
|
26
|
+
{}.tap do |h|
|
27
|
+
h[:metric] = metric[0...start_index]
|
28
|
+
end_index = metric.index('}')
|
29
|
+
h[:tags] = parse_tags metric[(start_index + 1)...end_index].strip
|
30
|
+
groups_str = metric[(end_index + 1)..-1]
|
31
|
+
if groups_str.size > 5 # length of by{} is 4
|
32
|
+
h[:group] = parse_groups groups_str
|
33
|
+
h[:group].each { |group| h[:tags][group] ||= ['*'] }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_tags(tags)
|
39
|
+
return if tags.nil?
|
40
|
+
rtags = {}
|
41
|
+
split_for(tags, ',').each do |tag|
|
42
|
+
tagk, tagv = split_for(tag, '=')
|
43
|
+
next if tagk.nil? || tagv.nil?
|
44
|
+
rtags[tagk] ||= []
|
45
|
+
rtags[tagk].concat tagv.split('|').uniq
|
46
|
+
end
|
47
|
+
rtags
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_groups(groups_str)
|
51
|
+
start_index = groups_str.index('{')
|
52
|
+
end_index = groups_str.index('}')
|
53
|
+
groups = groups_str[(start_index + 1)...end_index].strip
|
54
|
+
return [] if groups.empty?
|
55
|
+
split_for(groups, ',').map(&:strip)
|
56
|
+
end
|
57
|
+
|
58
|
+
def split_for(string, token = ':')
|
59
|
+
result = []
|
60
|
+
index = start = pos = 0
|
61
|
+
is_in_bracket = false
|
62
|
+
string.each_char do |char|
|
63
|
+
if char == '{'
|
64
|
+
is_in_bracket = true
|
65
|
+
elsif char == '}'
|
66
|
+
is_in_bracket = false
|
67
|
+
elsif char == token && !is_in_bracket
|
68
|
+
result[index] = string[start...pos]
|
69
|
+
index += 1
|
70
|
+
start = pos + 1
|
71
|
+
end
|
72
|
+
pos += 1
|
73
|
+
end
|
74
|
+
result[index] = string[start...pos]
|
75
|
+
result
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module CloudInsight
|
2
|
+
# :nodoc:
|
3
|
+
module Opentsdb
|
4
|
+
#:nodoc:
|
5
|
+
class << self
|
6
|
+
attr_accessor :host, :port
|
7
|
+
|
8
|
+
def configure
|
9
|
+
yield self
|
10
|
+
end
|
11
|
+
|
12
|
+
def host
|
13
|
+
@host || 'localhost'
|
14
|
+
end
|
15
|
+
|
16
|
+
def port
|
17
|
+
@port || 4242
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset
|
21
|
+
@host = nil
|
22
|
+
@port = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def logger
|
26
|
+
@logger ||= begin
|
27
|
+
Logger.new(STDOUT).tap { |logger| logger.datetime_format = '%Y-%m-%d %H:%M:%S' }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
require 'logger'
|
34
|
+
require 'net/http'
|
35
|
+
require 'cloudinsight/opentsdb/version'
|
36
|
+
require 'cloudinsight/opentsdb/client'
|
37
|
+
require 'cloudinsight/opentsdb/query_parser'
|
38
|
+
require 'cloudinsight/opentsdb/query_param'
|
39
|
+
require 'forwardable'
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opentsdb-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- lizhe
|
8
|
+
- luyingrui
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-05-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '10.0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '10.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: minitest
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '5.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: minitest-reporters
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ~>
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '1.1'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '1.1'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rubocop
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0.40'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.40'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: guard
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.13'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ~>
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '2.13'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: listen
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ~>
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '3.0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ~>
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '3.0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: guard-minitest
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ~>
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '2.4'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ~>
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '2.4'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: mocha
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ~>
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '1.1'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '1.1'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: pry
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ~>
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.10'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ~>
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.10'
|
140
|
+
description: A ruby client library for querying data by OpenTSDB HTTP API.
|
141
|
+
email:
|
142
|
+
- lnz013@qq.com
|
143
|
+
- luyingrui@oneapm.com
|
144
|
+
executables: []
|
145
|
+
extensions: []
|
146
|
+
extra_rdoc_files: []
|
147
|
+
files:
|
148
|
+
- README.md
|
149
|
+
- lib/cloudinsight/opentsdb.rb
|
150
|
+
- lib/cloudinsight/opentsdb/client.rb
|
151
|
+
- lib/cloudinsight/opentsdb/http_client.rb
|
152
|
+
- lib/cloudinsight/opentsdb/query_param.rb
|
153
|
+
- lib/cloudinsight/opentsdb/query_parser.rb
|
154
|
+
- lib/cloudinsight/opentsdb/version.rb
|
155
|
+
homepage: https://github.com/cloudinsight/opentsdb-ruby
|
156
|
+
licenses:
|
157
|
+
- MIT
|
158
|
+
metadata:
|
159
|
+
allowed_push_host: https://rubygems.org
|
160
|
+
post_install_message:
|
161
|
+
rdoc_options: []
|
162
|
+
require_paths:
|
163
|
+
- lib
|
164
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: 2.0.0
|
169
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
requirements: []
|
175
|
+
rubyforge_project:
|
176
|
+
rubygems_version: 2.4.5
|
177
|
+
signing_key:
|
178
|
+
specification_version: 4
|
179
|
+
summary: Ruby client for OpenTSDB HTTP Query API.
|
180
|
+
test_files: []
|