copperegg-revealmetrics 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Users/reto/Projects/copperegg-revealmetrics/CHANGELOG.md +60 -0
- data/Users/reto/Projects/copperegg-revealmetrics/Gemfile +3 -0
- data/Users/reto/Projects/copperegg-revealmetrics/Gemfile.lock +28 -0
- data/Users/reto/Projects/copperegg-revealmetrics/LICENSE +19 -0
- data/Users/reto/Projects/copperegg-revealmetrics/README.md +161 -0
- data/Users/reto/Projects/copperegg-revealmetrics/Rakefile +3 -0
- data/Users/reto/Projects/copperegg-revealmetrics/copperegg.gemspec +24 -0
- data/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg.rb +12 -0
- data/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/api.rb +24 -0
- data/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/custom_dashboard.rb +138 -0
- data/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/metric_group.rb +123 -0
- data/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/metric_sample.rb +22 -0
- data/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/mixins/persistence.rb +108 -0
- data/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/ver.rb +3 -0
- data/Users/reto/Projects/copperegg-revealmetrics/pkg/copperegg-revealmetrics-0.6.1.gem +0 -0
- data/Users/reto/Projects/copperegg-revealmetrics/test/custom_dashboard_test.rb +118 -0
- data/Users/reto/Projects/copperegg-revealmetrics/test/metric_group_test.rb +61 -0
- data/Users/reto/Projects/copperegg-revealmetrics/test/metric_sample_test.rb +6 -0
- data/test/custom_dashboard_test.rb +118 -0
- data/test/metric_group_test.rb +61 -0
- data/test/metric_sample_test.rb +6 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9b7bb1be69dca77240c15db94a5eebc10f30b005
|
4
|
+
data.tar.gz: b1d20e84a42d1885a62b2b484421bfa384e8c748
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e725f928629913a3c9e6ce970c2ffa7b4a77e5f64c891699e24b73a5812aaa4ea5d30e6f908e67fe528c2293904414202c21e21cdbd87cec253658972ced6708
|
7
|
+
data.tar.gz: 826f07d4c1bb2fb4f49d103e6018a743faee47aa511fc0c412680342862e95f4716238d0e2da26a45c55dc70c9d3912ae0ced630d43baeff9aac6aedd68acbce
|
@@ -0,0 +1,60 @@
|
|
1
|
+
## 0.6.2
|
2
|
+
- Fork from `CopperEgg/copperegg-ruby` to `cargomedia/copperegg-revealmetrics`
|
3
|
+
|
4
|
+
|
5
|
+
## 0.6.1 (January 17, 2013)
|
6
|
+
|
7
|
+
Changes:
|
8
|
+
|
9
|
+
- Existing metric groups are used rather than automatically versioning metric group name upon creation.
|
10
|
+
|
11
|
+
|
12
|
+
## 0.6.0 (January 3, 2013)
|
13
|
+
|
14
|
+
Changes:
|
15
|
+
|
16
|
+
- Substantial changes to syntax. API resources now represented by Ruby classes. See README for details.
|
17
|
+
- Replaced multi_json requirement with json_pure.
|
18
|
+
|
19
|
+
Features:
|
20
|
+
|
21
|
+
- Automatic dashboard creation for metric groups.
|
22
|
+
- Metric groups and custom dashboards can be updated and deleted.
|
23
|
+
- Client-side validation added.
|
24
|
+
- Added automated test suite.
|
25
|
+
|
26
|
+
Bugfixes:
|
27
|
+
|
28
|
+
- Metric group versioning is encorporated and recognized.
|
29
|
+
|
30
|
+
|
31
|
+
## 0.5.3 (Dec 21, 2012)
|
32
|
+
|
33
|
+
Changes:
|
34
|
+
|
35
|
+
- Remove Gemfile.lock from git tracking
|
36
|
+
|
37
|
+
Bugfixes:
|
38
|
+
|
39
|
+
- format to match changes in CopperEgg API
|
40
|
+
|
41
|
+
|
42
|
+
## 0.5.2 (Dec 3, 2012)
|
43
|
+
|
44
|
+
Bugfixes:
|
45
|
+
|
46
|
+
- add explicit requires to make 1.8.7 work
|
47
|
+
|
48
|
+
|
49
|
+
## 0.5.1 (Nov 5, 2012)
|
50
|
+
|
51
|
+
Changes:
|
52
|
+
|
53
|
+
- Use SSL
|
54
|
+
- updated gemspec and variable names
|
55
|
+
|
56
|
+
|
57
|
+
## 0.5.0 (Nov 5, 2012)
|
58
|
+
|
59
|
+
Initial commit
|
60
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
copperegg-revealmetrics (0.6.1)
|
5
|
+
json_pure (~> 1.7.6)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.2.5)
|
11
|
+
json_pure (1.7.7)
|
12
|
+
rake (10.4.2)
|
13
|
+
rspec (2.99.0)
|
14
|
+
rspec-core (~> 2.99.0)
|
15
|
+
rspec-expectations (~> 2.99.0)
|
16
|
+
rspec-mocks (~> 2.99.0)
|
17
|
+
rspec-core (2.99.2)
|
18
|
+
rspec-expectations (2.99.2)
|
19
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
20
|
+
rspec-mocks (2.99.3)
|
21
|
+
|
22
|
+
PLATFORMS
|
23
|
+
ruby
|
24
|
+
|
25
|
+
DEPENDENCIES
|
26
|
+
copperegg-revealmetrics!
|
27
|
+
rake
|
28
|
+
rspec (~> 2.0)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2013 CopperEgg Corporation, 2015 Cargo Media.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# CopperEgg Revealmetrics
|
2
|
+
|
3
|
+
This gem allows programmatic access to the CopperEgg Revealmetrics API.
|
4
|
+
|
5
|
+
This is a fork of the [official client](https://github.com/CopperEgg/copperegg-ruby), adding additional functionality.
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install copperegg-revealmetrics
|
11
|
+
```
|
12
|
+
|
13
|
+
## Getting Started
|
14
|
+
|
15
|
+
### Setup
|
16
|
+
|
17
|
+
``` ruby
|
18
|
+
require 'copperegg-revealmetrics'
|
19
|
+
CopperEgg::Api.apikey = "sdf87xxxxxxxxxxxxxxxxxxxxx" # from the web UI
|
20
|
+
```
|
21
|
+
|
22
|
+
### Get a metric group:
|
23
|
+
|
24
|
+
``` ruby
|
25
|
+
metric_group = CopperEgg::MetricGroup.find("my_metric_group")
|
26
|
+
metric_group.name
|
27
|
+
# => "my_metric_group"
|
28
|
+
metric_group.label
|
29
|
+
# => "My Metric Group"
|
30
|
+
metric_group.metrics
|
31
|
+
# => [#<CopperEgg::MetricGroup::Metric:0x007fb43aab2570 @position=0, @type="ce_gauge", @name="metric1", @label="Metric 1", @unit="b">]
|
32
|
+
```
|
33
|
+
|
34
|
+
### Create a metric group:
|
35
|
+
|
36
|
+
``` ruby
|
37
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_new_metric_group", :label => "Cool New Group Visible Name", :frequency => 60) # data is sent every 60 seconds
|
38
|
+
metric_group.metrics << {"type"=>"ce_gauge", "name"=>"active_connections", "unit"=>"Connections"}
|
39
|
+
metric_group.metrics << {"type"=>"ce_gauge", "name"=>"connections_accepts", "unit"=>"Connections"}
|
40
|
+
metric_group.metrics << {"type"=>"ce_gauge", "name"=>"connections_handled", "unit"=>"Connections"}
|
41
|
+
metric_group.metrics << {"type"=>"ce_gauge", "name"=>"connections_requested", "unit"=>"Connections"}
|
42
|
+
metric_group.metrics << {"type"=>"ce_gauge", "name"=>"reading", "unit"=>"Connections"}
|
43
|
+
metric_group.metrics << {"type"=>"ce_gauge", "name"=>"writing", "unit"=>"Connections"}
|
44
|
+
metric_group.metrics << {"type"=>"ce_gauge", "name"=>"waiting", "unit"=>"Connections"}
|
45
|
+
metric_group.save
|
46
|
+
```
|
47
|
+
|
48
|
+
If a metric group by the same name already exists, that one will rather than creating a new one. In addition, if the metric group was previously removed it will be restored.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
metric_group2 = CopperEgg::MetricGroup.new(:name => "my_new_metric_group", :label => "New Group Version 2", :frequency => 60)
|
52
|
+
metric_group2.metrics << {"type"=>"ce_counter", "name"=>"active_connections", "unit"=>"Connections"}
|
53
|
+
metric_group2.save # this will perform an update to change the type of the metric 'active_connections' from 'ce_gauge' to 'ce_counter'
|
54
|
+
|
55
|
+
metric_group2.name
|
56
|
+
# => "my_metric_group"
|
57
|
+
```
|
58
|
+
|
59
|
+
### Updating a metric group:
|
60
|
+
|
61
|
+
Labels, frequency, metric types and metric units can be updated and additional metrics can be added. Changes to the metric group name or names of metrics within will be ignored.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
metric_group.name = "this_will_be_ignored"
|
65
|
+
metric_group.label = "My New Metric Group"
|
66
|
+
metric_group.frequency = 5
|
67
|
+
metric_group.metrics << {"type"=>"ce_counter_f", "name"=>"new_metric"}
|
68
|
+
metric_group.save
|
69
|
+
|
70
|
+
metric_group.name
|
71
|
+
# => "my_metric_group"
|
72
|
+
metric_group.label
|
73
|
+
# => "My New Metric Group"
|
74
|
+
metric_group.frequency
|
75
|
+
# => 5
|
76
|
+
```
|
77
|
+
|
78
|
+
### Delete a metric group
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
metric_group.delete
|
82
|
+
```
|
83
|
+
|
84
|
+
|
85
|
+
### Post samples for a metric group
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
CopperEgg::MetricSample.save(metric_group.name, "custom_identifier1", Time.now.to_i, "active_connections" => 2601, "connections_accepts" => 154, "connections_handled" => 128, "connections_requested" => 1342, ...)
|
89
|
+
```
|
90
|
+
|
91
|
+
### Get samples
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
# Get the most recent samples for a single metric
|
95
|
+
CopperEgg::MetricSample.samples(metric_group.name, "connections_accepts")
|
96
|
+
|
97
|
+
# Get the most recent samples for multiple metrics
|
98
|
+
CopperEgg::MetricSample.samples(metric_group.name, ["connections_accepts", "connections_handled", "reading", "writing"])
|
99
|
+
|
100
|
+
# Specify a start time and duration
|
101
|
+
CopperEgg::MetricSample.samples(metric_group.name, ["connections_accepts", "connections_handled", "reading", "writing"], :starttime => 4.hours.ago, :duration => 15.minutes)
|
102
|
+
```
|
103
|
+
|
104
|
+
The raw JSON response is returned as specified in the [API docs][sample_docs].
|
105
|
+
|
106
|
+
### Create a dashboard from a metric group
|
107
|
+
|
108
|
+
By default, the dashboard created will be named "_MetricGroupLabel_ Dashboard" and will have one timeline widget per metric matching all sources.
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
# Creates a dashboard named "My Metric Group Dashboard"
|
112
|
+
dashboard = CopperEgg::CustomDashboard.create(metric_group)
|
113
|
+
```
|
114
|
+
|
115
|
+
You can pass an option to specify the name of the dashboard.
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
dashboard = CopperEgg::CustomDashboard.create(metric_group, :name => "Cloud Servers")
|
119
|
+
```
|
120
|
+
|
121
|
+
If a single identifier is specified, the dashboard will be created having one value widget per metric matching the single identifier.
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
dashboard = CopperEgg::CustomDashboard.create(metric_group, :name => "Cloud Servers", :identifiers => "custom_identifier1")
|
125
|
+
```
|
126
|
+
|
127
|
+
If an array of identifiers is specified, the dashboard will be created having one timeline widget per metric matching each identifier.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
dashboard = CopperEgg::CustomDashboard.create(metric_group, :name => "Cloud Servers", :identifiers => ["custom_identifier1", "custom_identifier2"])
|
131
|
+
```
|
132
|
+
|
133
|
+
You can limit the widgets created by metric.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
dashboard = CopperEgg::CustomDashboard.create(metric_group, :name => "Cloud Servers", :identifiers => ["custom_identifier1", "custom_identifier2"], :metrics => ["reading", "writing", "waiting"])
|
137
|
+
```
|
138
|
+
|
139
|
+
### Get a dashboard
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
dashboard = CopperEgg::CustomDashboard.find_by_name("My Metric Group Dashboard")
|
143
|
+
```
|
144
|
+
|
145
|
+
### Delete a dashboard
|
146
|
+
|
147
|
+
Dashboards can be deleted like metric groups:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
dashboard.delete
|
151
|
+
```
|
152
|
+
|
153
|
+
## Questions / Problems?
|
154
|
+
|
155
|
+
There are more detailed examples in the [test classes][test_classes].
|
156
|
+
|
157
|
+
Full [API docs][docs] are available.
|
158
|
+
|
159
|
+
[sample_docs]:http://dev.copperegg.com/revealmetrics/samples.html
|
160
|
+
[test_classes]:/test
|
161
|
+
[docs]:http://dev.copperegg.com
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path('../lib/copperegg/ver', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'copperegg-revealmetrics'
|
5
|
+
s.version = CopperEgg::GEM_VERSION
|
6
|
+
s.summary = 'API client for CopperEgg Revealmetrics'
|
7
|
+
s.description = 'API client for CopperEgg Revealmetrics'
|
8
|
+
s.authors = ['Eric Anderson', 'Cargo Media']
|
9
|
+
s.email = 'hello@cargomedia.ch'
|
10
|
+
s.homepage = 'https://github.com/cargomedia/copperegg-revealmetrics'
|
11
|
+
s.license = 'MIT'
|
12
|
+
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.require_paths = %w[lib]
|
15
|
+
s.files = Dir["#{File.dirname(__FILE__)}/**/*"]
|
16
|
+
s.test_files = Dir.glob("{test,spec,features}/*")
|
17
|
+
|
18
|
+
s.add_dependency('json_pure', '~> 1.7.6')
|
19
|
+
|
20
|
+
s.add_development_dependency 'rake'
|
21
|
+
s.add_development_dependency 'rspec', '~> 2.0'
|
22
|
+
|
23
|
+
s.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'copperegg-revealmetrics', '--main', 'README.md']
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "net/https"
|
3
|
+
require "uri"
|
4
|
+
require "json/pure"
|
5
|
+
require File.dirname(__FILE__) + "/copperegg/mixins/persistence"
|
6
|
+
require File.dirname(__FILE__) + "/copperegg/metric_group"
|
7
|
+
require File.dirname(__FILE__) + "/copperegg/custom_dashboard"
|
8
|
+
require File.dirname(__FILE__) + "/copperegg/metric_sample"
|
9
|
+
require File.dirname(__FILE__) + "/copperegg/api"
|
10
|
+
|
11
|
+
module CopperEgg
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module CopperEgg
|
2
|
+
class Api
|
3
|
+
class << self
|
4
|
+
attr_accessor :apikey
|
5
|
+
attr_reader :ssl_verify_peer, :timeout
|
6
|
+
|
7
|
+
def host=(host)
|
8
|
+
@uri = URI.join(host, "/v2/revealmetrics/").to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def uri
|
12
|
+
@uri || "https://api.copperegg.com/v2/revealmetrics/"
|
13
|
+
end
|
14
|
+
|
15
|
+
def ssl_verify_peer=(boolean)
|
16
|
+
@ssl_verify_peer = boolean ? true : false
|
17
|
+
end
|
18
|
+
|
19
|
+
def timeout=(seconds)
|
20
|
+
@timeout = seconds.to_i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module CopperEgg
|
2
|
+
class CustomDashboard
|
3
|
+
include CopperEgg::Mixins::Persistence
|
4
|
+
|
5
|
+
WIDGET_TYPES = %w(metric metric_list timeline)
|
6
|
+
WIDGET_STYLES = %w(value timeline both list values)
|
7
|
+
WIDGET_MATCHES = %w(select multi tag all)
|
8
|
+
|
9
|
+
resource "dashboards"
|
10
|
+
|
11
|
+
attr_accessor :name, :label, :data
|
12
|
+
|
13
|
+
def load_attributes(attributes)
|
14
|
+
@data = {"widgets" => {}, "order" => []}
|
15
|
+
attributes.each do |name, value|
|
16
|
+
if name.to_s == "id"
|
17
|
+
@id = value
|
18
|
+
elsif name.to_s == "data"
|
19
|
+
attributes[name].each do |data_name, data_value|
|
20
|
+
if data_name.to_s == "order"
|
21
|
+
data["order"] = data_value
|
22
|
+
else
|
23
|
+
data["widgets"] = data_value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
elsif !respond_to?("#{name}=")
|
27
|
+
next
|
28
|
+
else
|
29
|
+
send "#{name}=", value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid?
|
35
|
+
@error = nil
|
36
|
+
if self.name.nil? || self.name.to_s.strip.empty?
|
37
|
+
@error = "Name can't be blank."
|
38
|
+
else
|
39
|
+
self.data["widgets"].values.each do |widget|
|
40
|
+
widget.each do |key, value|
|
41
|
+
if key.to_s == "type" && !WIDGET_TYPES.include?(value)
|
42
|
+
@error = "Invalid widget type #{value}."
|
43
|
+
elsif key.to_s == "style" && !WIDGET_STYLES.include?(value)
|
44
|
+
@error = "Invalid widget style #{value}."
|
45
|
+
elsif key.to_s == "match" && !WIDGET_MATCHES.include?(value)
|
46
|
+
@error = "Invalid widget match #{value}."
|
47
|
+
elsif key.to_s == "metric" && (!value.is_a?(Hash) || value.keys.size == 0)
|
48
|
+
@error = "Invalid widget metric. #{value}"
|
49
|
+
else
|
50
|
+
(widget["metric"] || widget[:metric]).each do |metric_group_name, metric_group_value|
|
51
|
+
if !metric_group_value.is_a?(Array)
|
52
|
+
@error = "Invalid widget metric. #{metric_group_value}"
|
53
|
+
elsif metric_group_value.length == 0
|
54
|
+
@error = "Invalid widget metric. #{metric_group_value}"
|
55
|
+
else
|
56
|
+
metric_group_value.each do |metric_data|
|
57
|
+
if !metric_data.is_a?(Array)
|
58
|
+
@error = "Invalid widget metric. #{metric_group_value}"
|
59
|
+
elsif metric_data.length < 2
|
60
|
+
@error = "Invalid widget metric. #{metric_group_value}"
|
61
|
+
elsif (/^\d+$/ =~ metric_data.first.to_s).nil?
|
62
|
+
@error = "Invalid widget metric. #{metric_group_value}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
match_param = widget["match_param"] || widget[:match_param]
|
70
|
+
if (widget["match"] || widget[:match]) != "all" && (match_param.nil? || match_param.to_s.strip.empty?)
|
71
|
+
@error = "Missing match parameter."
|
72
|
+
end
|
73
|
+
break if !@error.nil?
|
74
|
+
end
|
75
|
+
end
|
76
|
+
@error.nil?
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_hash
|
80
|
+
set_data_order
|
81
|
+
self.instance_variables.reduce({}) do |memo, variable|
|
82
|
+
unless variable.to_s == "@error"
|
83
|
+
value = instance_variable_get(variable)
|
84
|
+
memo[variable.to_s.sub("@","")] = value
|
85
|
+
end
|
86
|
+
memo
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class <<self
|
91
|
+
def create(*args)
|
92
|
+
options = args.last.class == Hash ? args.pop : {}
|
93
|
+
|
94
|
+
return super(args.first) if args.first.is_a?(Hash)
|
95
|
+
|
96
|
+
metric_group = args.first
|
97
|
+
raise ArgumentError.new("CopperEgg::MetricGroup object expected") if !metric_group.is_a?(MetricGroup)
|
98
|
+
raise ArgumentError.new("Invalid metric group") if !metric_group.valid?
|
99
|
+
|
100
|
+
metrics = filter_metrics(metric_group, options[:metrics]).map { |name| metric_group.metrics.find {|metric| metric.name == name} }
|
101
|
+
identifiers = options[:identifiers].is_a?(Array) ? (options[:identifiers].empty? ? nil : options[:identifiers]) : (options[:identifier] ? [options[:identifiers]] : nil)
|
102
|
+
widget_match = identifiers.nil? ? "all" : (identifiers.size == 1 ? "select" : "multi")
|
103
|
+
widget_type = widget_match == "select" ? "metric" : "timeline"
|
104
|
+
widget_style = widget_type == "metric" ? "both" : "values"
|
105
|
+
name = options[:name] || "#{metric_group.label} Dashboard"
|
106
|
+
|
107
|
+
dashboard = new(:name => name)
|
108
|
+
metrics.each.with_index do |metric, i|
|
109
|
+
metric_data = [metric.position, metric.name]
|
110
|
+
metric_data.push("rate") if metric.type == "ce_counter" || metric.type == "ce_counter_f"
|
111
|
+
widget = {:type => widget_type, :style => widget_style, :match => widget_match, :metric => {metric_group.name => [metric_data]}}
|
112
|
+
widget[:match_param] = identifiers if identifiers
|
113
|
+
dashboard.data["widgets"][i.to_s] = widget
|
114
|
+
end
|
115
|
+
dashboard.save
|
116
|
+
dashboard
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_by_name(name)
|
120
|
+
find.detect {|dashboard| dashboard.name == name}
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def filter_metrics(metric_group, specified_metrics)
|
126
|
+
metrics = metric_group.metrics.map(&:name)
|
127
|
+
specified_metrics = specified_metrics.is_a?(Array) ? specified_metrics & metrics : (specified_metrics ? [specified_metrics] & metrics : [])
|
128
|
+
specified_metrics.empty? ? metrics : specified_metrics
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def set_data_order
|
135
|
+
@data["order"] = @data["widgets"].keys if @data["order"].empty?
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module CopperEgg
|
2
|
+
class MetricGroup
|
3
|
+
include CopperEgg::Mixins::Persistence
|
4
|
+
|
5
|
+
resource "metric_groups"
|
6
|
+
|
7
|
+
attr_accessor :name, :label, :frequency, :metrics
|
8
|
+
|
9
|
+
def load_attributes(attributes)
|
10
|
+
@metrics = []
|
11
|
+
attributes.each do |name, value|
|
12
|
+
if name.to_s == "id"
|
13
|
+
@id = value
|
14
|
+
elsif !respond_to?("#{name}=")
|
15
|
+
next
|
16
|
+
elsif value.to_s == "metrics"
|
17
|
+
@metrics = value.map {|v| Metric.new(v)}
|
18
|
+
else
|
19
|
+
send "#{name}=", value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_hash
|
25
|
+
self.instance_variables.reduce({}) do |memo, variable|
|
26
|
+
value = instance_variable_get(variable)
|
27
|
+
if variable.to_s == "@metrics"
|
28
|
+
memo[variable.to_s.sub("@","")] = value.map(&:to_hash)
|
29
|
+
elsif variable.to_s != "@error"
|
30
|
+
memo[variable.to_s.sub("@","")] = value
|
31
|
+
end
|
32
|
+
memo
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def valid?
|
37
|
+
@error = nil
|
38
|
+
if self.name.nil? || self.name.to_s.strip.empty?
|
39
|
+
@error = "Name can't be blank."
|
40
|
+
elsif self.metrics.nil? || self.metrics.empty?
|
41
|
+
@error = "You must define at least one metric."
|
42
|
+
else
|
43
|
+
self.metrics = self.metrics.map {|metric| metric.is_a?(Hash) ? Metric.new(metric) : metric}
|
44
|
+
self.metrics.each do |metric|
|
45
|
+
if !metric.is_a?(Metric)
|
46
|
+
@error = "Metric expected."
|
47
|
+
break
|
48
|
+
elsif !metric.valid?
|
49
|
+
@error = metric.error
|
50
|
+
break
|
51
|
+
else
|
52
|
+
metric.send(:remove_instance_variable, :@position) if (metric.instance_variables.include?(:@position) || metric.instance_variables.include?("@position")) && !self.persisted?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@error.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def create
|
62
|
+
response = self.class.request(:request_type => "get", :id => self.name, :show_hidden => true)
|
63
|
+
if response.code == "200"
|
64
|
+
json = JSON.parse(response.body)
|
65
|
+
metric_group = self.class.new(json)
|
66
|
+
@id = self.name
|
67
|
+
# needs_update = self.label != metric_group.label || self.frequency != metric_group.frequency || self.metrics.length != metric_group.metrics.length || self.metrics.map(&:name).sort != metric_group.metrics.map {|m| m["name"]}.sort
|
68
|
+
if true #needs_update
|
69
|
+
self.class.request(self.to_hash.merge(:id => @id, :is_hidden => 0, :request_type => "put", :show_hidden => true))
|
70
|
+
else
|
71
|
+
response
|
72
|
+
end
|
73
|
+
else
|
74
|
+
self.class.request(self.to_hash.merge(:request_type => "post"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class Metric
|
79
|
+
TYPES = %w(ce_gauge ce_gauge_f ce_counter ce_counter_f)
|
80
|
+
|
81
|
+
attr_accessor :name, :label, :type, :unit
|
82
|
+
attr_reader :error, :position
|
83
|
+
|
84
|
+
def initialize(attributes={})
|
85
|
+
attributes.each do |name, value|
|
86
|
+
if name.to_s == "position"
|
87
|
+
@position = value
|
88
|
+
elsif !respond_to?("#{name}=")
|
89
|
+
next
|
90
|
+
else
|
91
|
+
send "#{name}=", value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_hash
|
97
|
+
self.instance_variables.reduce({}) do |memo, variable|
|
98
|
+
if variable.to_s != "@error"
|
99
|
+
value = instance_variable_get(variable)
|
100
|
+
memo[variable.to_s.sub("@","")] = value
|
101
|
+
end
|
102
|
+
memo
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def valid?
|
107
|
+
valid = false
|
108
|
+
@error = nil
|
109
|
+
if self.name.nil? || self.name.to_s.strip.empty?
|
110
|
+
@error = "Metric name cannot be blank."
|
111
|
+
elsif self.type.nil? || self.type.to_s.strip.empty?
|
112
|
+
@error = "Metric type must be defined."
|
113
|
+
elsif !TYPES.include?(self.type)
|
114
|
+
@error = "Invalid metric type #{self.type}."
|
115
|
+
else
|
116
|
+
valid = true
|
117
|
+
remove_instance_variable(:@error)
|
118
|
+
end
|
119
|
+
valid
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CopperEgg
|
2
|
+
class MetricSample
|
3
|
+
include CopperEgg::Mixins::Persistence
|
4
|
+
|
5
|
+
resource "samples"
|
6
|
+
|
7
|
+
def self.save(group_name, identifier, timestamp, metric_values)
|
8
|
+
request(:id => group_name, :identifier => identifier, :timestamp => timestamp, :values => metric_values, :request_type => "post")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.samples(group_name, metrics, starttime=nil, duration=nil, sample_size=nil)
|
12
|
+
metrics = [metrics] unless metrics.is_a?(Array)
|
13
|
+
params = {}
|
14
|
+
params[:starttime] = starttime if starttime
|
15
|
+
params[:duration] = duration if duration
|
16
|
+
params[:sample_size] = sample_size if sample_size
|
17
|
+
params[:queries] = {group_name => [{:metrics => metrics}]}
|
18
|
+
|
19
|
+
request(params.merge(:request_type => "get"))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module CopperEgg
|
2
|
+
class ValidationError < Exception; end
|
3
|
+
|
4
|
+
module Mixins
|
5
|
+
module Persistence
|
6
|
+
def self.included(klass)
|
7
|
+
klass.class_eval do
|
8
|
+
class << self
|
9
|
+
attr_reader :resource_name
|
10
|
+
|
11
|
+
def find(*args)
|
12
|
+
params = args.last.class == Hash ? args.pop : {}
|
13
|
+
id = args.first
|
14
|
+
response = request(params.merge(:request_type => "get", :id => id))
|
15
|
+
if response.code == "200"
|
16
|
+
json = JSON.parse(response.body)
|
17
|
+
if json.is_a?(Array)
|
18
|
+
json.map {|attributes| new(attributes)}
|
19
|
+
else
|
20
|
+
new(json)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(params)
|
26
|
+
params.delete(:id)
|
27
|
+
params.delete("id")
|
28
|
+
new(params).save
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete(id)
|
32
|
+
request(:id => id, :request_type => "delete")
|
33
|
+
end
|
34
|
+
|
35
|
+
def request(params={})
|
36
|
+
request_type = params.delete(:request_type)
|
37
|
+
raise "invalid type" if !%w(get post put delete).include?(request_type)
|
38
|
+
id = params.delete(:id)
|
39
|
+
|
40
|
+
uri = id ? URI.parse("#{Api.uri}/#{self.resource_name}/#{id}.json") : URI.parse("#{Api.uri}/#{self.resource_name}.json")
|
41
|
+
|
42
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
43
|
+
http.use_ssl = uri.scheme == 'https'
|
44
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if !Api.ssl_verify_peer
|
45
|
+
|
46
|
+
request = Net::HTTP.const_get(request_type.capitalize).new(uri.request_uri)
|
47
|
+
request.body = JSON.generate(params) unless params.empty?
|
48
|
+
request.basic_auth(Api.apikey, "U")
|
49
|
+
request["Content-Type"] = "application/json"
|
50
|
+
|
51
|
+
begin
|
52
|
+
response = http.request(request)
|
53
|
+
rescue Exception => e
|
54
|
+
raise e
|
55
|
+
end
|
56
|
+
|
57
|
+
response
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def resource(value)
|
63
|
+
@resource_name = value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
attr_reader :id, :error
|
70
|
+
|
71
|
+
def initialize(attributes={})
|
72
|
+
load_attributes(attributes)
|
73
|
+
end
|
74
|
+
|
75
|
+
def save
|
76
|
+
if valid?
|
77
|
+
response = persisted? ? update : create
|
78
|
+
attributes = JSON.parse(response.body)
|
79
|
+
if response.code != "200"
|
80
|
+
@error = attributes.merge("code" => response.code)
|
81
|
+
else
|
82
|
+
load_attributes(attributes)
|
83
|
+
end
|
84
|
+
else
|
85
|
+
raise ValidationError.new(@error)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete
|
90
|
+
self.class.request(:id => @id, :request_type => "delete")
|
91
|
+
end
|
92
|
+
|
93
|
+
def persisted?
|
94
|
+
!@id.nil?
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def create
|
100
|
+
self.class.request(to_hash.merge(:request_type => "post"))
|
101
|
+
end
|
102
|
+
|
103
|
+
def update
|
104
|
+
self.class.request(to_hash.merge(:id => @id, :request_type => "put"))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
Binary file
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "copperegg"
|
3
|
+
|
4
|
+
class CustomDashboardTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_name_accessor_and_setter
|
7
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
8
|
+
|
9
|
+
assert_equal "My Dashboard", dashboard.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_save_should_fail_if_name_is_not_set
|
13
|
+
dashboard = CopperEgg::CustomDashboard.new
|
14
|
+
|
15
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
16
|
+
assert_equal "Name can't be blank.", error.message
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_save_should_fail_for_an_invalid_widget_type
|
20
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
21
|
+
dashboard.data["widgets"]["0"] = {:type => "foo", :style => "value", :match => "tag", :match_param => ["test"],
|
22
|
+
:metric => {"my_metric_group" => [[0, "metric1"]]}}
|
23
|
+
|
24
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
25
|
+
assert_equal "Invalid widget type foo.", error.message
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_save_should_fail_for_an_invalid_widget_style
|
29
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
30
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "foo", :match => "tag", :match_param => ["test"],
|
31
|
+
:metric => {"my_metric_group" => [[0, "metric1"]]}}
|
32
|
+
|
33
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
34
|
+
assert_equal "Invalid widget style foo.", error.message
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_save_should_ail_for_an_invalidvwidget_match
|
38
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
39
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "foo", :match_param => ["test"],
|
40
|
+
:metric => {"my_metric_group" => [[0, "metric1"]]}}
|
41
|
+
|
42
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
43
|
+
assert_equal "Invalid widget match foo.", error.message
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_save_should_fail_for_a_missing_match_parameter
|
47
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
48
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "select", :metric => {"my_metric_group" => [[0, "metric1"]]}}
|
49
|
+
|
50
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
51
|
+
assert_equal "Missing match parameter.", error.message
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_save_should_fail_if_metric_is_not_a_hash
|
55
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
56
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => ["my_metric_group", 0, "metric1"]}
|
57
|
+
|
58
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
59
|
+
assert_match /invalid widget metric/i, error.message
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_save_should_fail_if_metric_does_not_contain_an_array
|
63
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
64
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => "metric1"}}
|
65
|
+
|
66
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
67
|
+
assert_match /invalid widget metric/i, error.message
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_save_should_fail_if_metric_contains_an_empty_array
|
71
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
72
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => []}}
|
73
|
+
|
74
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
75
|
+
assert_match /invalid widget metric/i, error.message
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_save_should_fail_if_metric_contains_an_array_with_invalid_values
|
79
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
80
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => ["metric1"]}}
|
81
|
+
|
82
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
83
|
+
assert_match /invalid widget metric/i, error.message
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_save_should_fail_if_metric_contains_an_array_with_an_invalid_position
|
87
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
88
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => [["four", "metric1"]]}}
|
89
|
+
|
90
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
91
|
+
assert_match /invalid widget metric/i, error.message
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_save_should_fail_if_metric_contains_an_array_with_no_metric_name
|
95
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
96
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => [[0]]}}
|
97
|
+
|
98
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
99
|
+
assert_match /invalid widget metric/i, error.message
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_to_hash
|
103
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
104
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => [[1, "metric1"]]}}
|
105
|
+
|
106
|
+
assert dashboard.valid?
|
107
|
+
|
108
|
+
hash = dashboard.to_hash
|
109
|
+
|
110
|
+
assert_equal "My Dashboard", hash["name"]
|
111
|
+
assert_equal "metric", hash["data"]["widgets"]["0"][:type]
|
112
|
+
assert_equal "value", hash["data"]["widgets"]["0"][:style]
|
113
|
+
assert_equal "tag", hash["data"]["widgets"]["0"][:match]
|
114
|
+
assert_equal ["test"], hash["data"]["widgets"]["0"][:match_param]
|
115
|
+
assert_equal [[1, "metric1"]], hash["data"]["widgets"]["0"][:metric]["my_metric_group"]
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "copperegg"
|
3
|
+
|
4
|
+
class MetricGroupTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_name_accessor_and_setter
|
7
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group")
|
8
|
+
|
9
|
+
assert_equal "my_metric_group", metric_group.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_save_should_fail_if_name_is_blank
|
13
|
+
metric_group = CopperEgg::MetricGroup.new
|
14
|
+
|
15
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
16
|
+
assert_equal "Name can't be blank.", error.message
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_save_should_fail_if_no_metrics_are_declared
|
20
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group")
|
21
|
+
|
22
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
23
|
+
assert_equal "You must define at least one metric.", error.message
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_save_should_fail_if_metrics_include_non_metric
|
27
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group", :metrics => ["metric"])
|
28
|
+
|
29
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
30
|
+
assert_equal "Metric expected.", error.message
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_save_should_fail_for_invalid_metric
|
34
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group", :metrics => [{:name => "test", :type => "invalid"}])
|
35
|
+
|
36
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
37
|
+
assert_equal "Invalid metric type invalid.", error.message
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_to_hash
|
41
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "test", :label => "Test Metric", :frequency => 5)
|
42
|
+
metric_group.metrics << {:type => "ce_counter", :name => "metric1", :label => "Metric 1", :unit => "ticks"}
|
43
|
+
metric_group.metrics << {:type => "ce_counter_f", :name => "metric2", :label => "Metric 2"}
|
44
|
+
|
45
|
+
assert metric_group.valid?
|
46
|
+
hash = metric_group.to_hash
|
47
|
+
|
48
|
+
assert_nil hash["id"]
|
49
|
+
assert_equal "test", hash["name"]
|
50
|
+
assert_equal "Test Metric", hash["label"]
|
51
|
+
assert_equal 5, hash["frequency"]
|
52
|
+
assert_equal "ce_counter", hash["metrics"].first["type"]
|
53
|
+
assert_equal "metric1", hash["metrics"].first["name"]
|
54
|
+
assert_equal "Metric 1", hash["metrics"].first["label"]
|
55
|
+
assert_equal "ticks", hash["metrics"].first["unit"]
|
56
|
+
assert_equal "ce_counter_f", hash["metrics"].last["type"]
|
57
|
+
assert_equal "metric2", hash["metrics"].last["name"]
|
58
|
+
assert_equal "Metric 2", hash["metrics"].last["label"]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "copperegg"
|
3
|
+
|
4
|
+
class CustomDashboardTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_name_accessor_and_setter
|
7
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
8
|
+
|
9
|
+
assert_equal "My Dashboard", dashboard.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_save_should_fail_if_name_is_not_set
|
13
|
+
dashboard = CopperEgg::CustomDashboard.new
|
14
|
+
|
15
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
16
|
+
assert_equal "Name can't be blank.", error.message
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_save_should_fail_for_an_invalid_widget_type
|
20
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
21
|
+
dashboard.data["widgets"]["0"] = {:type => "foo", :style => "value", :match => "tag", :match_param => ["test"],
|
22
|
+
:metric => {"my_metric_group" => [[0, "metric1"]]}}
|
23
|
+
|
24
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
25
|
+
assert_equal "Invalid widget type foo.", error.message
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_save_should_fail_for_an_invalid_widget_style
|
29
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
30
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "foo", :match => "tag", :match_param => ["test"],
|
31
|
+
:metric => {"my_metric_group" => [[0, "metric1"]]}}
|
32
|
+
|
33
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
34
|
+
assert_equal "Invalid widget style foo.", error.message
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_save_should_ail_for_an_invalidvwidget_match
|
38
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
39
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "foo", :match_param => ["test"],
|
40
|
+
:metric => {"my_metric_group" => [[0, "metric1"]]}}
|
41
|
+
|
42
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
43
|
+
assert_equal "Invalid widget match foo.", error.message
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_save_should_fail_for_a_missing_match_parameter
|
47
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
48
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "select", :metric => {"my_metric_group" => [[0, "metric1"]]}}
|
49
|
+
|
50
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
51
|
+
assert_equal "Missing match parameter.", error.message
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_save_should_fail_if_metric_is_not_a_hash
|
55
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
56
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => ["my_metric_group", 0, "metric1"]}
|
57
|
+
|
58
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
59
|
+
assert_match /invalid widget metric/i, error.message
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_save_should_fail_if_metric_does_not_contain_an_array
|
63
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
64
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => "metric1"}}
|
65
|
+
|
66
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
67
|
+
assert_match /invalid widget metric/i, error.message
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_save_should_fail_if_metric_contains_an_empty_array
|
71
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
72
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => []}}
|
73
|
+
|
74
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
75
|
+
assert_match /invalid widget metric/i, error.message
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_save_should_fail_if_metric_contains_an_array_with_invalid_values
|
79
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
80
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => ["metric1"]}}
|
81
|
+
|
82
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
83
|
+
assert_match /invalid widget metric/i, error.message
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_save_should_fail_if_metric_contains_an_array_with_an_invalid_position
|
87
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
88
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => [["four", "metric1"]]}}
|
89
|
+
|
90
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
91
|
+
assert_match /invalid widget metric/i, error.message
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_save_should_fail_if_metric_contains_an_array_with_no_metric_name
|
95
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
96
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => [[0]]}}
|
97
|
+
|
98
|
+
error = assert_raise(CopperEgg::ValidationError) { dashboard.save }
|
99
|
+
assert_match /invalid widget metric/i, error.message
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_to_hash
|
103
|
+
dashboard = CopperEgg::CustomDashboard.new(:name => "My Dashboard")
|
104
|
+
dashboard.data["widgets"]["0"] = {:type => "metric", :style => "value", :match => "tag", :match_param => ["test"], :metric => {"my_metric_group" => [[1, "metric1"]]}}
|
105
|
+
|
106
|
+
assert dashboard.valid?
|
107
|
+
|
108
|
+
hash = dashboard.to_hash
|
109
|
+
|
110
|
+
assert_equal "My Dashboard", hash["name"]
|
111
|
+
assert_equal "metric", hash["data"]["widgets"]["0"][:type]
|
112
|
+
assert_equal "value", hash["data"]["widgets"]["0"][:style]
|
113
|
+
assert_equal "tag", hash["data"]["widgets"]["0"][:match]
|
114
|
+
assert_equal ["test"], hash["data"]["widgets"]["0"][:match_param]
|
115
|
+
assert_equal [[1, "metric1"]], hash["data"]["widgets"]["0"][:metric]["my_metric_group"]
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "copperegg"
|
3
|
+
|
4
|
+
class MetricGroupTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_name_accessor_and_setter
|
7
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group")
|
8
|
+
|
9
|
+
assert_equal "my_metric_group", metric_group.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_save_should_fail_if_name_is_blank
|
13
|
+
metric_group = CopperEgg::MetricGroup.new
|
14
|
+
|
15
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
16
|
+
assert_equal "Name can't be blank.", error.message
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_save_should_fail_if_no_metrics_are_declared
|
20
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group")
|
21
|
+
|
22
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
23
|
+
assert_equal "You must define at least one metric.", error.message
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_save_should_fail_if_metrics_include_non_metric
|
27
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group", :metrics => ["metric"])
|
28
|
+
|
29
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
30
|
+
assert_equal "Metric expected.", error.message
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_save_should_fail_for_invalid_metric
|
34
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "my_metric_group", :metrics => [{:name => "test", :type => "invalid"}])
|
35
|
+
|
36
|
+
error = assert_raise(CopperEgg::ValidationError) { metric_group.save }
|
37
|
+
assert_equal "Invalid metric type invalid.", error.message
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_to_hash
|
41
|
+
metric_group = CopperEgg::MetricGroup.new(:name => "test", :label => "Test Metric", :frequency => 5)
|
42
|
+
metric_group.metrics << {:type => "ce_counter", :name => "metric1", :label => "Metric 1", :unit => "ticks"}
|
43
|
+
metric_group.metrics << {:type => "ce_counter_f", :name => "metric2", :label => "Metric 2"}
|
44
|
+
|
45
|
+
assert metric_group.valid?
|
46
|
+
hash = metric_group.to_hash
|
47
|
+
|
48
|
+
assert_nil hash["id"]
|
49
|
+
assert_equal "test", hash["name"]
|
50
|
+
assert_equal "Test Metric", hash["label"]
|
51
|
+
assert_equal 5, hash["frequency"]
|
52
|
+
assert_equal "ce_counter", hash["metrics"].first["type"]
|
53
|
+
assert_equal "metric1", hash["metrics"].first["name"]
|
54
|
+
assert_equal "Metric 1", hash["metrics"].first["label"]
|
55
|
+
assert_equal "ticks", hash["metrics"].first["unit"]
|
56
|
+
assert_equal "ce_counter_f", hash["metrics"].last["type"]
|
57
|
+
assert_equal "metric2", hash["metrics"].last["name"]
|
58
|
+
assert_equal "Metric 2", hash["metrics"].last["label"]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: copperegg-revealmetrics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eric Anderson
|
8
|
+
- Cargo Media
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-03-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json_pure
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 1.7.6
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 1.7.6
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2.0'
|
56
|
+
description: API client for CopperEgg Revealmetrics
|
57
|
+
email: hello@cargomedia.ch
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/CHANGELOG.md"
|
63
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/Gemfile"
|
64
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/Gemfile.lock"
|
65
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/LICENSE"
|
66
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/README.md"
|
67
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/Rakefile"
|
68
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/copperegg.gemspec"
|
69
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg.rb"
|
70
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/api.rb"
|
71
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/custom_dashboard.rb"
|
72
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/metric_group.rb"
|
73
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/metric_sample.rb"
|
74
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/mixins/persistence.rb"
|
75
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/lib/copperegg/ver.rb"
|
76
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/pkg/copperegg-revealmetrics-0.6.1.gem"
|
77
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/test/custom_dashboard_test.rb"
|
78
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/test/metric_group_test.rb"
|
79
|
+
- "/Users/reto/Projects/copperegg-revealmetrics/test/metric_sample_test.rb"
|
80
|
+
- test/custom_dashboard_test.rb
|
81
|
+
- test/metric_group_test.rb
|
82
|
+
- test/metric_sample_test.rb
|
83
|
+
homepage: https://github.com/cargomedia/copperegg-revealmetrics
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options:
|
89
|
+
- "--line-numbers"
|
90
|
+
- "--inline-source"
|
91
|
+
- "--title"
|
92
|
+
- copperegg-revealmetrics
|
93
|
+
- "--main"
|
94
|
+
- README.md
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.4.5
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: API client for CopperEgg Revealmetrics
|
113
|
+
test_files:
|
114
|
+
- test/custom_dashboard_test.rb
|
115
|
+
- test/metric_group_test.rb
|
116
|
+
- test/metric_sample_test.rb
|