newrelic_plugin 1.0.3 → 1.2.1

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.
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