newrelic_plugin 1.0.3 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG.md +44 -1
  3. data/README.md +11 -5
  4. data/lib/newrelic_platform_binding.rb +11 -0
  5. data/lib/newrelic_platform_binding/component.rb +27 -0
  6. data/lib/newrelic_platform_binding/config.rb +39 -0
  7. data/lib/newrelic_platform_binding/connection.rb +86 -0
  8. data/lib/newrelic_platform_binding/context.rb +49 -0
  9. data/lib/newrelic_platform_binding/logger.rb +40 -0
  10. data/lib/newrelic_platform_binding/metric.rb +49 -0
  11. data/lib/newrelic_platform_binding/request.rb +111 -0
  12. data/lib/newrelic_plugin.rb +1 -4
  13. data/lib/newrelic_plugin/agent.rb +14 -21
  14. data/lib/newrelic_plugin/config.rb +2 -1
  15. data/lib/newrelic_plugin/processors/rate_processor.rb +3 -3
  16. data/lib/newrelic_plugin/run.rb +97 -54
  17. data/lib/newrelic_plugin/setup.rb +10 -19
  18. data/lib/newrelic_plugin/version.rb +1 -1
  19. data/newrelic_plugin.gemspec +4 -4
  20. data/test/newrelic_platform_binding/component_test.rb +16 -0
  21. data/test/newrelic_platform_binding/config_test.rb +89 -0
  22. data/test/newrelic_platform_binding/connection_test.rb +67 -0
  23. data/test/newrelic_platform_binding/context_test.rb +35 -0
  24. data/test/newrelic_platform_binding/logger_test.rb +33 -0
  25. data/test/newrelic_platform_binding/metric_test.rb +97 -0
  26. data/test/newrelic_platform_binding/request_test.rb +127 -0
  27. data/test/newrelic_plugin/agent_test.rb +127 -0
  28. data/test/newrelic_plugin/run_test.rb +77 -0
  29. data/test/newrelic_plugin/setup_test.rb +17 -0
  30. data/test/test_helper.rb +11 -4
  31. metadata +59 -17
  32. data/lib/newrelic_plugin/data_collector.rb +0 -67
  33. data/lib/newrelic_plugin/logger.rb +0 -19
  34. data/lib/newrelic_plugin/new_relic_connection.rb +0 -67
  35. data/lib/newrelic_plugin/new_relic_message.rb +0 -173
  36. data/test/agent_test.rb +0 -153
  37. data/test/logger_test.rb +0 -21
  38. data/test/manual_test.rb +0 -20
  39. data/test/new_relic_message_test.rb +0 -76
@@ -0,0 +1,77 @@
1
+ require 'test_helper'
2
+
3
+ class RunTest < Minitest::Test
4
+ TestConfig = Struct.new(:newrelic)
5
+ def setup
6
+ @newrelic = {
7
+ }
8
+ end
9
+
10
+ def test_log_level_set_verbose
11
+ NewRelic::Logger.expects(:log_level=).with(::Logger::DEBUG)
12
+ @newrelic['verbose'] = 1
13
+ initialize_run
14
+ end
15
+
16
+ def test_log_level_not_set
17
+ NewRelic::Logger.expects(:log_level=).never
18
+ initialize_run
19
+ end
20
+
21
+ def test_log_level_set_to_not_verbose
22
+ NewRelic::Logger.expects(:log_level=).never
23
+ @newrelic['verbose'] = 0
24
+ initialize_run
25
+ end
26
+
27
+ def test_endpoint_config
28
+ NewRelic::Binding::Config.expects(:endpoint=).with('http://test.com')
29
+ @newrelic['endpoint'] = 'http://test.com'
30
+ initialize_run
31
+ end
32
+
33
+ def test_ssl_host_verification_nil
34
+ NewRelic::Binding::Config.expects(:ssl_host_verification=).never
35
+ initialize_run
36
+ end
37
+
38
+ def test_ssl_host_verification_string
39
+ NewRelic::Binding::Config.expects(:ssl_host_verification=).with(true)
40
+ @newrelic['ssl_host_verification'] = 'foo'
41
+ initialize_run
42
+ end
43
+
44
+ def test_ssl_host_verification_false
45
+ NewRelic::Binding::Config.expects(:ssl_host_verification=).with(false)
46
+ @newrelic['ssl_host_verification'] = false
47
+ initialize_run
48
+ end
49
+
50
+ def test_ssl_host_verification_true
51
+ NewRelic::Binding::Config.expects(:ssl_host_verification=).with(true)
52
+ @newrelic['ssl_host_verification'] = true
53
+ initialize_run
54
+ end
55
+
56
+ def test_proxy
57
+ NewRelic::Binding::Config.expects(:proxy=).with('foobar')
58
+ @newrelic['proxy'] = 'foobar'
59
+ initialize_run
60
+ end
61
+
62
+ def test_poll_cycle_period_without_poll_set
63
+ NewRelic::Binding::Config.expects(:poll_cycle_period=).with(60)
64
+ initialize_run
65
+ end
66
+
67
+ def test_poll_cycle_period_with_poll_set
68
+ NewRelic::Binding::Config.expects(:poll_cycle_period=).with(20)
69
+ @newrelic['poll'] = 20
70
+ initialize_run
71
+ end
72
+
73
+ def initialize_run
74
+ NewRelic::Plugin::Config.stubs(:config).returns(TestConfig.new(@newrelic))
75
+ NewRelic::Plugin::Run.new()
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+
4
+ class SetupTest < Minitest::Test
5
+
6
+ def setup
7
+ @context = NewRelic::Binding::Context.new('license_key')
8
+ end
9
+
10
+
11
+ def test_create_agent
12
+ setup = NewRelic::Plugin::AgentSetup.new
13
+ @context.expects(:version=).with('0.0.1')
14
+ setup.create_agent(@context, 'testing_agent', nil)
15
+ end
16
+
17
+ end
@@ -1,15 +1,22 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
3
  Bundler.setup
4
+ require 'newrelic_platform_binding'
4
5
  require 'newrelic_plugin'
5
- require 'test/unit'
6
- require 'shoulda-context'
7
- require 'mocha'
6
+ require 'minitest/autorun'
7
+ require 'mocha/setup'
8
+ require 'pry'
9
+ require 'timecop'
8
10
 
9
11
 
10
12
  module TestingAgent
13
+ NewRelic::Logger.log_level = ::Logger::FATAL
11
14
  class Agent < NewRelic::Plugin::Agent::Base
12
-
15
+ agent_guid 'com.newrelic.test'
16
+ agent_version '0.0.1'
17
+ agent_human_labels("Testing") { "Testing host" }
13
18
  end
19
+
20
+ NewRelic::Plugin::Setup.install_agent 'testing_agent', TestingAgent
14
21
  end
15
22
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: newrelic_plugin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,16 +9,16 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-25 00:00:00.000000000 Z
12
+ date: 2013-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: faraday
15
+ name: json
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.8.1
21
+ version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,16 +26,48 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 0.8.1
29
+ version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
- name: json
31
+ name: mocha
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
35
  - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
37
  version: '0'
38
- type: :runtime
38
+ type: :development
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: minitest
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 5.0.6
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 5.0.6
62
+ - !ruby/object:Gem::Dependency
63
+ name: fakeweb
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
39
71
  prerelease: false
40
72
  version_requirements: !ruby/object:Gem::Requirement
41
73
  none: false
@@ -44,7 +76,7 @@ dependencies:
44
76
  - !ruby/object:Gem::Version
45
77
  version: '0'
46
78
  - !ruby/object:Gem::Dependency
47
- name: shoulda-context
79
+ name: pry
48
80
  requirement: !ruby/object:Gem::Requirement
49
81
  none: false
50
82
  requirements:
@@ -60,7 +92,7 @@ dependencies:
60
92
  - !ruby/object:Gem::Version
61
93
  version: '0'
62
94
  - !ruby/object:Gem::Dependency
63
- name: mocha
95
+ name: timecop
64
96
  requirement: !ruby/object:Gem::Requirement
65
97
  none: false
66
98
  requirements:
@@ -91,14 +123,18 @@ files:
91
123
  - LICENSE
92
124
  - README.md
93
125
  - Rakefile
126
+ - lib/newrelic_platform_binding.rb
127
+ - lib/newrelic_platform_binding/component.rb
128
+ - lib/newrelic_platform_binding/config.rb
129
+ - lib/newrelic_platform_binding/connection.rb
130
+ - lib/newrelic_platform_binding/context.rb
131
+ - lib/newrelic_platform_binding/logger.rb
132
+ - lib/newrelic_platform_binding/metric.rb
133
+ - lib/newrelic_platform_binding/request.rb
94
134
  - lib/newrelic_plugin.rb
95
135
  - lib/newrelic_plugin/agent.rb
96
136
  - lib/newrelic_plugin/config.rb
97
- - lib/newrelic_plugin/data_collector.rb
98
137
  - lib/newrelic_plugin/error.rb
99
- - lib/newrelic_plugin/logger.rb
100
- - lib/newrelic_plugin/new_relic_connection.rb
101
- - lib/newrelic_plugin/new_relic_message.rb
102
138
  - lib/newrelic_plugin/processor.rb
103
139
  - lib/newrelic_plugin/processors/epoch_counter_processor.rb
104
140
  - lib/newrelic_plugin/processors/rate_processor.rb
@@ -107,11 +143,17 @@ files:
107
143
  - lib/newrelic_plugin/simple_syntax.rb
108
144
  - lib/newrelic_plugin/version.rb
109
145
  - newrelic_plugin.gemspec
110
- - test/agent_test.rb
111
146
  - test/fixtures/valid_payload.json
112
- - test/logger_test.rb
113
- - test/manual_test.rb
114
- - test/new_relic_message_test.rb
147
+ - test/newrelic_platform_binding/component_test.rb
148
+ - test/newrelic_platform_binding/config_test.rb
149
+ - test/newrelic_platform_binding/connection_test.rb
150
+ - test/newrelic_platform_binding/context_test.rb
151
+ - test/newrelic_platform_binding/logger_test.rb
152
+ - test/newrelic_platform_binding/metric_test.rb
153
+ - test/newrelic_platform_binding/request_test.rb
154
+ - test/newrelic_plugin/agent_test.rb
155
+ - test/newrelic_plugin/run_test.rb
156
+ - test/newrelic_plugin/setup_test.rb
115
157
  - test/test_helper.rb
116
158
  homepage: http://newrelic.com
117
159
  licenses: []
@@ -1,67 +0,0 @@
1
- module NewRelic
2
- module Plugin
3
- #
4
- # Gather's data from agent and presents it to nr_connect for processing.
5
- #
6
- # This is a wrapper for nr_connect used in the context of an agent.
7
- #
8
- class DataCollector
9
- #
10
- #
11
- # Methods used within an agent implementation:
12
- #
13
- #
14
- def add_data metric_name,units,data,opts={}
15
- nrmsg.add_stat_fullname(
16
- "Component/#{metric_name}[#{units}]",
17
- 1,
18
- data,
19
- :min => data,
20
- :max => data,
21
- :sum_of_squares => (data*data)
22
- )
23
- #puts "Metric '#{metric_name}' (#{units}): raw: #{value}, processed: #{data} (#{processor_type})" if verbose?
24
- @cnt+=1
25
- data
26
- end
27
-
28
-
29
- #
30
- # Internal methods used within Agent class
31
- #
32
- def initialize agent,poll_interval
33
- @agent=agent
34
- @poll_interval=poll_interval
35
- @cnt=0
36
- end
37
- def process
38
- nrmsg_send
39
- @cnt
40
- end
41
-
42
- ################################################################################
43
- private
44
-
45
- def verbose?
46
- return @verbose unless @verbose.nil?
47
- @verbose=NewRelic::Plugin::Config.config.newrelic["verbose"].to_i>0
48
- end
49
-
50
- #
51
- # NewRelicConnection Handling
52
- #
53
- def nrmsg
54
- @nrmsg||=nrobj.start_message @agent.instance_label,@agent.guid,@agent.version,@poll_interval
55
- end
56
- def nrmsg_send
57
- return unless @nrmsg
58
- @nrmsg.send_metrics
59
- @nrmsg=nil
60
- end
61
- def nrobj
62
- @nrobj||=NewRelic::Plugin::NewRelicConnection.new NewRelic::Plugin::Config.config.newrelic
63
- end
64
-
65
- end
66
- end
67
- end
@@ -1,19 +0,0 @@
1
- module NewRelic
2
- module Plugin
3
- require 'time'
4
-
5
- class Logger
6
- def self.write(message)
7
- Logger.output "[#{Logger.timestamp}] #{message}"
8
- end
9
-
10
- def self.output(message)
11
- puts message
12
- end
13
-
14
- def self.timestamp
15
- Time.iso8601(Time.now.utc.iso8601).to_s
16
- end
17
- end
18
- end
19
- end
@@ -1,67 +0,0 @@
1
- require 'faraday'
2
-
3
- module NewRelic
4
- module Plugin
5
- class NewRelicConnection
6
- #
7
- # Allowed configuration Values:
8
- # license_key [required] Specifies RPM account to store metrics in
9
- # host [optional] override default production collector
10
- # port [optional] override default production collector
11
- # verbose [optional] log HTTP transactions to stdout
12
- #
13
- def initialize config = {}
14
- @config = config
15
- end
16
- #
17
- # Start creating a message containing a set of metrics to New Relic.
18
- #
19
- def start_message component_name,component_guid,component_version,duration_in_seconds
20
- NewRelic::Plugin::NewRelicMessage.new self,component_name,component_guid,component_version,duration_in_seconds
21
- end
22
-
23
- #################### Internal Only
24
- #
25
- # Create HTTP tunnel to New Relic
26
- #
27
- def connect
28
- @connect ||= Faraday.new(:url => url, :ssl => { :verify => ssl_host_verification } ) do |builder|
29
- builder.request :url_encoded
30
- builder.response :logger if @config["log_http"].to_i>0
31
- builder.use AuthenticationMiddleware,license_key
32
- builder.adapter :net_http
33
- end
34
- end
35
- def url
36
- @config["endpoint"] || "https://platform-api.newrelic.com"
37
- end
38
- def uri
39
- @config["uri"] || "/platform/v1/metrics"
40
- end
41
- def ssl_host_verification
42
- ssl_host_verification = @config["ssl_host_verification"]
43
- return true if ssl_host_verification.nil?
44
- !!ssl_host_verification
45
- end
46
- class AuthenticationMiddleware < Faraday::Middleware
47
- def initialize(app,apikey)
48
- super(app)
49
- @apikey = apikey
50
- end
51
- def call(env)
52
- unless env[:request_headers]['X-License-Key']
53
- env[:request_headers]['X-License-Key'] = @apikey
54
- end
55
- @app.call(env)
56
- end
57
- end
58
- def log_metrics?
59
- @config["verbose"] || @config["log_metrics"]
60
- end
61
- def license_key
62
- @config["license_key"]
63
- end
64
-
65
- end
66
- end
67
- end
@@ -1,173 +0,0 @@
1
- require 'json'
2
-
3
- module NewRelic
4
- module Plugin
5
- #
6
- # NewRelic driver. Provides all methods necessary for accessing the NewRelic service.
7
- # Used to store data into NewRelic service.
8
- #
9
- # Usage:
10
- #
11
- # nrobj=NewRelic::Plugin::NewRelicConnection.new license_key:"xxx",host:"xxx",port:80,log_http:true,log_metrics:true # log_http,host and port are optional; license key is not.
12
- # msg=nrobj.start_message <component_name>,<component_guid>,<component_version>,<duration_in_seconds>
13
- # msg.add_stat basename,count_unit,value_unit,count,value,opts={} # opts can include :min, :max, and :sum_of_squares
14
- # msg.send_message # Send the list of stats to New Relic
15
- #
16
- # Example:
17
- # nrobj=NewRelic::Plugin::NewRelicConnection.new license_key:"bootstrap_newrelic_admin_license_key_000",host:"localhost",port:8081,log_http:true,log_metrics:true
18
- # msg=nrobj.start_message "A Kewl Component","12345678","0.0.1",60
19
- # msg.add_stat_fullname "Component/TestMetric1[Bytes/Seconds]",2,34,min:31,max:54,sum_of_squares:1234
20
- # msg.add_stat_fullname "Component/AnotherTest[Bytes/Seconds]",2,34,min:31,max:54,sum_of_squares:1234
21
- # msg.add_stat_fullname "Component/TestMetric2[Bytes/Seconds]",2,34,min:31,max:54,sum_of_squares:1234
22
- # msg.add_stat_fullname "Component/AnotherMetric[Bytes/Seconds]",2,34,min:31,max:54,sum_of_squares:1234
23
- # msg.send_metrics # Send the list of stats to New Relic
24
- #
25
-
26
-
27
-
28
- class NewRelicMessage
29
- #
30
- #
31
- # Create an object to send metrics
32
- #
33
- #
34
- def initialize connection,component_name,component_guid,component_version,duration_in_seconds
35
- @connection = connection
36
- @component_name = component_name
37
- @component_guid = component_guid
38
- @component_version = component_version
39
- @duration_in_seconds = duration_in_seconds
40
- @metrics = [] # Metrics being saved
41
- end
42
- def add_stat_fullname metric_name,count,value,opts={}
43
- entry = {}
44
- entry[:metric_name] = metric_name
45
- entry[:count] = count
46
- entry[:total] = value
47
- [:min,:max,:sum_of_squares].each do |key|
48
- entry[key] = opts[key]
49
- end
50
- @metrics << entry
51
- end
52
-
53
- def metrics
54
- @metrics
55
- end
56
-
57
- def send_metrics
58
- return_errors = []
59
- Logger.write "Metrics for #{@component_name}[#{@component_guid}] for last #{@duration_in_seconds} seconds:" if new_relic_connection.log_metrics?
60
- #
61
- # Send all metrics in a single transaction
62
- #
63
- response = deliver_metrics
64
- evaluate_response(response)
65
- log_send_metrics
66
- end
67
-
68
- private
69
-
70
- def build_metrics_hash
71
- metrics_hash = {}
72
- metrics.each do |metric|
73
- metric_value = []
74
- [:total,:count,:max,:min,:sum_of_squares].each do |key|
75
- metric_value.push(metric[key]) if metric[key]
76
- end
77
- metrics_hash[metric[:metric_name]] = metric_value
78
- end
79
- return metrics_hash
80
- end
81
-
82
- def build_request_payload
83
- data = {
84
- "agent" => {
85
- "name" => @component_name,
86
- "version" => @component_version,
87
- "host" => ""
88
- },
89
- "components" => [
90
- {
91
- "name" => @component_name,
92
- "guid" => @component_guid,
93
- "duration" => @duration_in_seconds,
94
- "metrics" => build_metrics_hash
95
- }
96
- ]
97
- }
98
- return data.to_json
99
- end
100
-
101
- def deliver_metrics
102
- begin
103
- response = new_relic_connection.connect.post do |req|
104
- req.url new_relic_connection.uri
105
- req.headers['Content-Type'] = 'application/json'
106
- req.body = build_request_payload
107
- end
108
- rescue => err
109
- Logger.write "HTTP Connection Error: #{err.inspect} #{err.message}"
110
- end
111
-
112
- return response
113
- end
114
-
115
- def evaluate_response(response)
116
- return_status = nil
117
- if response.nil?
118
- last_result={"error" => "no response"}
119
- return_status = "FAILED: No response"
120
- elsif response && response.status == 200
121
- last_result = JSON.parse(response.body)
122
- if last_result["status"] != "ok"
123
- return_status = "FAILED[#{response.status}] <#{new_relic_connection.url}>: #{last_result["error"]}"
124
- end
125
- elsif response && response.status == 403 && response.body == "DISABLE_NEW_RELIC"
126
- Logger.write "Agent has been disabled remotely by New Relic"
127
- abort "Agent has been disabled remotely by New Relic"
128
- else
129
- begin
130
- if response.body.size>0
131
- last_result = JSON.parse(response.body)
132
- else
133
- last_result = {"error" => "no data returned"}
134
- end
135
- return_status = "FAILED[#{response.status}] <#{new_relic_connection.url}>: #{last_result["error"]}"
136
- rescue => err
137
- if response
138
- return_status = "FAILED[#{response.status}] <#{new_relic_connection.url}>: Could not parse response: #{err}"
139
- else
140
- return_status = "FAILED: #{err}"
141
- end
142
- end
143
- end
144
- if return_status
145
- if response and response.status == 503 and !new_relic_connection.log_metrics?
146
- # If logging not enabled, and it's a 503...be less error-ish...
147
- Logger.write " Collector temporarily unavailable...continuing"
148
- else
149
- # Otherwise, in all cases (logging enabled or not) print an error message
150
- Logger.write " ****ERROR: #{return_status}"
151
- end
152
- end
153
- end
154
-
155
- def log_send_metrics
156
- if new_relic_connection.log_metrics?
157
- Logger.write " Sent #{metrics.size} metrics to New Relic [#{new_relic_connection.url}]:"
158
- metrics.each do |metric|
159
- val_strs = []
160
- [:count,:total,:min,:max,:sum_of_squares].each do |key|
161
- val_strs << "#{key}: #{metric[key]}" if metric[key]
162
- end
163
- Logger.write " #{metric[:metric_name]}: #{val_strs.join(', ')}"
164
- end
165
- end
166
- end
167
-
168
- def new_relic_connection
169
- @connection
170
- end
171
- end
172
- end
173
- end