multiforecast-client 0.62.0.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1316eee0e12243629951f3a621150271e5df2a3f
4
+ data.tar.gz: f4cb9e1be15332f4f7cf51036f2d509ef93926c6
5
+ SHA512:
6
+ metadata.gz: 61b291a15bbf7ce71c80783ef984ac3b56cc2a10862a8ccce2ae05034848dabf72bc6926f3bbd9fed495adcf0c8d5f4494636e29f250c0c723256564118ebb6f
7
+ data.tar.gz: 0cc4d55285915ff7334b047076c52efa49a3b5dc52d9fcddef604804260da1a5f33ccc9efdcbf37f6da602ad0c1849e100b362fc0d9ccbbcf78181bdffd89e0e
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /*.gem
2
+ ~*
3
+ #*
4
+ *~
5
+ .bundle
6
+ Gemfile.lock
7
+ .rbenv-version
8
+ .ruby-version
9
+ vendor
10
+ doc/*
11
+ tags
12
+ tmp/*
13
+ .yardoc
14
+ multiforecast.yml
data/.pryrc ADDED
@@ -0,0 +1,5 @@
1
+ Pry.commands.alias_command 'c', 'continue'
2
+ Pry.commands.alias_command 's', 'step'
3
+ Pry.commands.alias_command 'n', 'next'
4
+ Pry.commands.alias_command 'f', 'finish'
5
+
data/.rdebugrc ADDED
@@ -0,0 +1,4 @@
1
+ set autolist
2
+ set autoeval
3
+ set autoreload
4
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ # - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+ gemfile:
7
+ - Gemfile
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # 0.62.0.1 (2013/07/06)
2
+
3
+ First version
4
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ source 'https://rubygems.org'
3
+
4
+ gemspec
5
+ gem 'multiforecast-client', path: '.'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Naotoshi SEO
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,96 @@
1
+ # multiforecast-client
2
+
3
+ testing ruby: 1.9.2, 1.9.3, 2.0.0; GrowthForecast: >= 0.62 (Jun 27, 2013 released)
4
+
5
+ ## About multiforecast-client
6
+
7
+ `multiforecast-client` is a Multiple GrowthForecast Client, aimed to be used for [Yohoushi](https://github.com/yohoushi/yohoushi) visualization tool.
8
+
9
+ Features
10
+
11
+ - Possible to send http requests to multiple growthforecasts seemlessly
12
+ - Enables to create graphs whose levels are more than 3.
13
+ - CRUD graphs
14
+ - Get graph image uri
15
+
16
+ ## USAGE
17
+
18
+ ### Library
19
+
20
+ Create a client.
21
+
22
+ ```ruby
23
+ require 'multiforecast-client'
24
+ client = MultiForecast::Client.new('mapping' => {
25
+ 'foo/' => 'http://localhost:5125',
26
+ '' => 'http://localhost:5000'
27
+ })
28
+ ```
29
+
30
+ The first `post_graph` posts a number to the first GrowthForecast.
31
+ The second `post_graph` posts a number to the second GrowthForecast because the specified path did not match with the first mapping rule 'foo/'.
32
+ Notice that the pattern matching is processed from top as ruby's hash is an ordered hash.
33
+
34
+ ```ruby
35
+ client.post_graph('foo/b/c/d', { 'number' => 0 })
36
+ client.post_graph('bar/b/c/d', { 'number' => 0 })
37
+ ```
38
+
39
+ See [examples](./examples) for more.
40
+
41
+ ### CLI
42
+
43
+ `multiforecast-client` also provides a CLI named `multiforecast`.
44
+
45
+ Generate a config file template to store a mapping rule:
46
+
47
+ ```
48
+ $ multiforecast genearte config
49
+ Generated multiforecast.yml
50
+ $ cat multiforecast.yml
51
+ ---
52
+ mapping:
53
+ '': http://localhost:5125
54
+ short_metrics: true
55
+ ```
56
+
57
+ Post a number and create a graph:
58
+
59
+ ```
60
+ $ multiforecast post '{"number":0}' 'foo/a/b/c' -c multiforecast.yml
61
+ ```
62
+
63
+ Delete a graph or graphs under a path:
64
+
65
+ ```
66
+ $ multiforecast delete 'foo/' -c multiforecast.yml
67
+ ```
68
+
69
+ See help for more:
70
+
71
+ ```
72
+ $ multiforecast help
73
+ ```
74
+
75
+ ## INSIDE: How to treat graphs of more than 3 levels
76
+
77
+ Although GrowthForecast can treat only graphs of 3 leveled path, MultiForecast can handle graphs of more than 3 levels.
78
+ This feature is achieved by converting a given path to GrowthForecast's `service_name/section_name/graph_name` path as follows:
79
+
80
+ service_name = 'multiforecast'
81
+ section_name = CGI.escape(File.dirname(path)).gsub('+', '%20').gsub('.', '%2E')
82
+ graph_name = File.basename(path)
83
+
84
+ As a viewer for these converted path, [Yohoushi](https://github.com/yohoushi/yohoushi) is ready for you.
85
+
86
+ ## Contributing
87
+
88
+ 1. Fork it
89
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
90
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
91
+ 4. Push to the branch (`git push origin my-new-feature`)
92
+ 5. Create new [Pull Request](../../pull/new/master)
93
+
94
+ ## Copyright
95
+
96
+ Copyright (c) 2013 Naotoshi SEO. See [LICENSE](LICENSE) for details.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+ task :default => :spec
10
+
11
+ desc 'Open an irb session preloaded with the gem library'
12
+ task :console do
13
+ sh 'irb -rubygems -I lib -r multiforecast-client.rb'
14
+ end
15
+ task :c => :console
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.62.0.2
data/bin/multiforecast ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'multiforecast/cli'
5
+ MultiForecast::CLI.start(ARGV)
@@ -0,0 +1,161 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'multiforecast-client'
3
+ require 'pp'
4
+
5
+ ### Create a Multi GrowthForecast Client
6
+ client = MultiForecast::Client.new('mapping' => {
7
+ 'app1/' => 'http://localhost:5125',
8
+ 'app2/' => 'http://localhost:5000'
9
+ })
10
+ # client.debug_dev = STDOUT # print out HTTP requests and responses
11
+
12
+ pp 'Create a graph (Post a number)'
13
+ client.post_graph('app1/2xx_count', { 'number' => 0 })
14
+ client.post_graph('app1/3xx_count', { 'number' => 0 })
15
+ pp client.post_graph('app2/2xx_count', { 'number' => 0 }) #=>
16
+ # {"error"=>0,
17
+ # "data"=>
18
+ # {"number"=>0,
19
+ # "llimit"=>-1000000000,
20
+ # "mode"=>"gauge",
21
+ # "stype"=>"AREA",
22
+ # "adjustval"=>"1",
23
+ # "meta"=>"",
24
+ # "service_name"=>"multiforecast",
25
+ # "gmode"=>"gauge",
26
+ # "color"=>"#33cc99",
27
+ # "created_at"=>"2013/05/20 17:57:57",
28
+ # "section_name"=>"multiforecast",
29
+ # "ulimit"=>1000000000,
30
+ # "id"=>2,
31
+ # "graph_name"=>"app2%2F2xx_count",
32
+ # "description"=>"",
33
+ # "sulimit"=>100000,
34
+ # "unit"=>"",
35
+ # "sort"=>0,
36
+ # "updated_at"=>"2013/05/20 17:57:57",
37
+ # "adjust"=>"*",
38
+ # "type"=>"AREA",
39
+ # "sllimit"=>-100000,
40
+ # "md5"=>"c81e728d9d4c2f636f067f89cc14862c"}}
41
+
42
+ pp 'List graphs. All graphs from multiple growthforecasts are shown'
43
+ pp client.list_graph #=>
44
+ # [{"graph_name"=>"app1%2F3xx_count",
45
+ # "service_name"=>"multiforecast",
46
+ # "section_name"=>"multiforecast",
47
+ # "id"=>2,
48
+ # "base_uri"=>"http://localhost:5125",
49
+ # "path"=>"app1/3xx_count"},
50
+ # {"graph_name"=>"app1%2F2xx_count",
51
+ # "service_name"=>"multiforecast",
52
+ # "section_name"=>"multiforecast",
53
+ # "id"=>1,
54
+ # "base_uri"=>"http://localhost:5125",
55
+ # "path"=>"app1/2xx_count"},
56
+ # {"service_name"=>"multiforecast",
57
+ # "graph_name"=>"app2%2F2xx_count",
58
+ # "section_name"=>"multiforecast",
59
+ # "id"=>2,
60
+ # "base_uri"=>"http://localhost:5000",
61
+ # "path"=>"app2/2xx_count"}]
62
+
63
+ pp 'List graphs by filtering by dirpath app1/'
64
+ pp client.list_graph('app1/') #=>
65
+ # [{"graph_name"=>"app1%2F3xx_count",
66
+ # "service_name"=>"multiforecast",
67
+ # "section_name"=>"multiforecast",
68
+ # "id"=>2,
69
+ # "base_uri"=>"http://localhost:5125",
70
+ # "path"=>"app1/3xx_count"},
71
+ # {"graph_name"=>"app1%2F2xx_count",
72
+ # "service_name"=>"multiforecast",
73
+ # "section_name"=>"multiforecast",
74
+ # "id"=>1,
75
+ # "base_uri"=>"http://localhost:5125",
76
+ # "path"=>"app1/2xx_count"}]
77
+
78
+ pp 'Get a graph property'
79
+ pp client.get_graph('app2/2xx_count') #=>
80
+ # {"number"=>0,
81
+ # "llimit"=>-1000000000,
82
+ # "mode"=>"gauge",
83
+ # "stype"=>"AREA",
84
+ # "adjustval"=>"1",
85
+ # "meta"=>"",
86
+ # "service_name"=>"multiforecast",
87
+ # "gmode"=>"gauge",
88
+ # "color"=>"#33cc99",
89
+ # "created_at"=>"2013/05/20 17:57:57",
90
+ # "section_name"=>"multiforecast",
91
+ # "ulimit"=>1000000000,
92
+ # "id"=>2,
93
+ # "graph_name"=>"app2%2F2xx_count",
94
+ # "description"=>"",
95
+ # "sulimit"=>100000,
96
+ # "unit"=>"",
97
+ # "sort"=>0,
98
+ # "updated_at"=>"2013/05/20 17:57:57",
99
+ # "adjust"=>"*",
100
+ # "type"=>"AREA",
101
+ # "sllimit"=>-100000,
102
+ # "md5"=>"c81e728d9d4c2f636f067f89cc14862c",
103
+ # "base_uri"=>"http://localhost:5000",
104
+ # "path"=>"app2/2xx_count"}
105
+
106
+ pp 'Get a graph image uri'
107
+ pp client.get_graph_uri('app2/2xx_count', term: '3h') #=>
108
+ # "http://localhost:5125/graph/multiforecast/multiforecast/app1%2F2xx_count?t=3h"
109
+
110
+ pp 'Delete a complex graph'
111
+ pp client.delete_graph('app2/2xx_count') #=>
112
+ # {"location"=>"http://localhost:5000/list/multiforecast/multiforecast", "error"=>0}
113
+
114
+ pp 'Create a complex graph'
115
+ # Source graphs of a complex graph must exist on *a* GrowthForecast
116
+ from_graphs= [
117
+ {"path"=>'app1/2xx_count', "gmode" => 'gauge', "stack" => true, "type" => 'AREA'},
118
+ {"path"=>'app1/3xx_count', "gmode" => 'gauge', "stack" => true, "type" => 'AREA'},
119
+ ]
120
+ to_complex = {
121
+ 'path' => 'app1/complex',
122
+ "description" => "response time count",
123
+ "sort" => 10,
124
+ }
125
+ pp client.create_complex(from_graphs, to_complex) #=>
126
+ # {"location"=>"http://localhost:5125/list/multiforecast/multiforecast", "error"=>0}
127
+
128
+ pp 'Get a complex graph'
129
+ pp client.get_complex(to_complex['path']) #=>
130
+ # {"number"=>0,
131
+ # "complex"=>true,
132
+ # "created_at"=>"2013/05/20 18:00:09",
133
+ # "service_name"=>"multiforecast",
134
+ # "section_name"=>"multiforecast",
135
+ # "id"=>1,
136
+ # "graph_name"=>"app1%2Fcomplex",
137
+ # "data"=>
138
+ # [{"gmode"=>"gauge", "stack"=>false, "type"=>"AREA", "graph_id"=>1},
139
+ # {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>2}],
140
+ # "sumup"=>false,
141
+ # "description"=>"response time count",
142
+ # "sort"=>10,
143
+ # "updated_at"=>"2013/05/20 18:00:09",
144
+ # "base_uri"=>"http://localhost:5125",
145
+ # "path"=>"app1/complex"}
146
+
147
+ pp 'Get a complex graph image uri'
148
+ pp client.get_complex_uri(to_complex['path'], term: '3h') #=>
149
+ # "http://localhost:5125/complex/graph/multiforecast/multiforecast/app1%2Fcomplex?t=3h"
150
+
151
+ pp 'List complex graphs'
152
+ pp client.list_complex #=>
153
+ # [{"service_name"=>"multiforecast", "graph_name"=>"app1%2Fcomplex", "section_name"=>"multiforecast", "id"=>1, "base_uri"=>"http://localhost:5125", "path"=>"app1/complex"}]
154
+
155
+ pp 'List complex graphs by filetering by dirpath app1/'
156
+ pp client.list_complex('app1/')
157
+
158
+ pp 'Delete a complex graph'
159
+ pp client.delete_complex(to_complex['path']) #=>
160
+ # {"location"=>"http://localhost:5125/list/multiforecast/multiforecast", "error"=>0}
161
+
@@ -0,0 +1,69 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'thor'
3
+ require 'yaml'
4
+ require 'multiforecast-client'
5
+
6
+ class MultiForecast::CLI < Thor
7
+ class_option :config, :aliases => ["-c"], :type => :string
8
+ class_option :silent, :aliases => ["-S"], :type => :boolean
9
+
10
+ def initialize(args = [], opts = [], config = {})
11
+ super(args, opts, config)
12
+
13
+ if options['config'] && File.exists?(options['config'])
14
+ @options = YAML.load_file(options['config']).merge(@options)
15
+ end
16
+ @client = MultiForecast::Client.new(@options)
17
+ end
18
+
19
+ desc 'generate config', 'Generate a sample config file'
20
+ def generate(target)
21
+ config = {
22
+ 'mapping' => { '' => 'http://localhost:5125' },
23
+ }
24
+ File.open("multiforecast.yml", "w") do |file|
25
+ YAML.dump(config, file)
26
+ $stdout.puts "Generated #{file.path}"
27
+ end
28
+ end
29
+
30
+ desc 'post <json> <path>', 'Post a parameter to a path'
31
+ long_desc <<-LONGDESC
32
+ Post a parameter to a path
33
+
34
+ ex)
35
+ $ multiforecast post '{"number":0}' 'test/test' -c multiforecast.yml
36
+ LONGDESC
37
+ def post(json, path)
38
+ begin
39
+ res = @client.post_graph(path, JSON.parse(json))
40
+ $stdout.puts res unless @options['silent']
41
+ rescue => e
42
+ $stderr.puts "\tclass:#{e.class}\t#{e.message}"
43
+ end
44
+ end
45
+
46
+ desc 'delete <base_path>', 'Delete a graph or graphs under a path'
47
+ def delete(base_path)
48
+ graphs = @client.list_graph(base_path)
49
+ graphs.each do |graph|
50
+ begin
51
+ @client.delete_graph(graph['path'])
52
+ $stdout.puts "Deleted #{graph['path']}" unless @options['silent']
53
+ rescue => e
54
+ $stderr.puts "\tclass:#{e.class}\t#{e.message}"
55
+ end
56
+ end
57
+ complexes = @client.list_complex(base_path)
58
+ complexes.each do |graph|
59
+ begin
60
+ @client.delete_complex(graph['path'])
61
+ $stdout.puts "Deleted #{graph['path']}" unless @options['silent']
62
+ rescue => e
63
+ puts "\tclass:#{e.class}\t#{e.message}"
64
+ end
65
+ end
66
+ $stderr.puts "Not found" if graphs.empty? and complexes.empty? unless @options['silent']
67
+ end
68
+ end
69
+