newrelic_plugin 1.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.
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in newrelic_plugin.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2013 New Relic, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # New Relic Platform Agent SDK
2
+
3
+ ## Requirements
4
+
5
+ * Tested with Ruby 1.8.7 and 1.9.3
6
+ * New Relic account on rpm.newrelic.com, with early access enabled
7
+ (contact cooper@newrelic.com to set up early access)
8
+
9
+ ## Get Started
10
+
11
+ This repo represents the core Ruby gem used to build plugin agents for
12
+ the New Relic platform. If you are looking to build or use a platform
13
+ component, please refer to the
14
+ [getting started documentation](http://newrelic.com/docs/platform/plugin-development).
15
+
16
+ Until this gem is published in rubygems.org, you will need to use this
17
+ gem by adding it to your [bundler](http://gembundler.com/) Gemfile like this:
18
+
19
+ ```ruby
20
+ gem "newrelic_plugin", :git => "git@github.com:newrelic-platform/newrelic_plugin.git", :branch => "release"
21
+ ```
22
+
23
+ Alternatively you can build and install the gem locally:
24
+
25
+ ```bash
26
+ git clone git@github.com:newrelic-platform/newrelic_plugin.git
27
+ cd newrelic_plugin
28
+ rake build
29
+ gem install pkg/newrelic_plugin*
30
+ ```
31
+
32
+ ## Support
33
+
34
+ Reach out to us at
35
+ [support.newrelic.com](http://support.newrelic.com/).
36
+ There you'll find documentation, FAQs, and forums where you can submit
37
+ suggestions and discuss with staff and other users.
38
+
39
+ Also available is community support on IRC: we generally use #newrelic
40
+ on irc.freenode.net
41
+
42
+ Find a bug? E-mail <support@newrelic.com>, or submit a ticket to
43
+
44
+ [support.newrelic.com](http://support.newrelic.com/).
45
+
46
+ Thank you!
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+ require "bundler/gem_tasks"
5
+
6
+ #############################################################################
7
+ #
8
+ # Standard tasks
9
+ #
10
+ #############################################################################
11
+
12
+ task :default => :test
13
+
14
+ require 'rake/testtask'
15
+ Rake::TestTask.new(:test) do |test|
16
+ test.libs << 'lib' << 'test'
17
+ test.pattern = 'test/**/*_test.rb'
18
+ test.verbose = true
19
+ end
@@ -0,0 +1,12 @@
1
+ require "newrelic_plugin/version"
2
+ require "newrelic_plugin/error"
3
+ require "newrelic_plugin/config"
4
+ require "newrelic_plugin/new_relic_connection"
5
+ require "newrelic_plugin/new_relic_message"
6
+ require "newrelic_plugin/agent"
7
+ require "newrelic_plugin/data_collector"
8
+ require "newrelic_plugin/setup" # cleanup needed
9
+ require "newrelic_plugin/run" # cleanup needed
10
+ require "newrelic_plugin/processor"
11
+ require "newrelic_plugin/processors/epoch_counter_processor" # port needed
12
+ require "newrelic_plugin/processors/rate_processor" # port needed
@@ -0,0 +1,155 @@
1
+ module NewRelic
2
+ module Plugin
3
+ #
4
+ # Primary newrelic_plugin agent.
5
+ #
6
+ # Author:: Lee Atchison <lee@newrelic.com>
7
+ # Copyright:: Copyright (c) 2012 New Relic, Inc.
8
+ #
9
+ module Agent
10
+ class Base
11
+ class << self
12
+ attr_reader :label,:instance_label_proc,:guid,:version
13
+ attr_accessor :config_options_list
14
+
15
+
16
+ #
17
+ # Define the GUID for this agent.
18
+ #
19
+ def agent_guid str
20
+ raise "Did not set GUID" if str.nil? or str==""
21
+ @guid=str
22
+ end
23
+
24
+ #
25
+ # Define version for this agent
26
+ #
27
+ def agent_version str
28
+ @version = str
29
+ end
30
+
31
+ #
32
+ #
33
+ # Human Readable labels for plugin.
34
+ # label - Name of the plugin
35
+ # block return - Name of a particular instance of a plugin component.
36
+ #
37
+ #
38
+ def agent_human_labels label,&block
39
+ @label=label
40
+ @instance_label_proc=block
41
+ end
42
+
43
+ #
44
+ #
45
+ # Support for single instance, non-configurable agents.
46
+ #
47
+ #
48
+ def no_config_required
49
+ @no_config_required=true
50
+ end
51
+ def config_required?
52
+ !@no_config_required
53
+ end
54
+
55
+ #
56
+ #
57
+ # Specify name of configuration values used in plugin implementation.
58
+ #
59
+ #
60
+ def agent_config_options *args
61
+ @config_options_list||=[]
62
+ args.each do |config|
63
+ attr_accessor config
64
+ @config_options_list << config
65
+ end
66
+ end
67
+ end
68
+
69
+ #
70
+ # Instance Info
71
+ #
72
+ attr_reader :name,:agent_info
73
+ def guid
74
+ return @guid if @guid
75
+ @guid=self.class.guid
76
+ #
77
+ # Verify GUID is set correctly...
78
+ #
79
+ if @guid=="guid" or @guid=="_TYPE_YOUR_GUID_HERE_"
80
+ #this feels tightly coupled to the config class, testing this is difficult, thinking about refactoring (NH)
81
+ @guid = NewRelic::Plugin::Config.config.newrelic['guids'][agent_info[:ident].to_s] if NewRelic::Plugin::Config.config.newrelic['guids']
82
+ puts "NOTE: GUID updated for #{instance_label} at run-time to '#{@guid}'"
83
+ end
84
+ raise "Did not set GUID" if @guid.nil? or @guid=="" or @guid=="guid" or @guid=="_TYPE_YOUR_GUID_HERE_"
85
+ @guid
86
+ end
87
+ def version
88
+ self.class.version
89
+ end
90
+ def label
91
+ self.class.label
92
+ end
93
+ #
94
+ # Instantiate a newrelic_plugin instance
95
+ def initialize name,agent_info,options={}
96
+ @name=name
97
+ @agent_info=agent_info
98
+ @ident=agent_info[:ident]
99
+ @options=options
100
+ if self.class.config_options_list
101
+ self.class.config_options_list.each do |config|
102
+ self.send("#{config}=",options[config])
103
+ end
104
+ end
105
+ @last_time=nil
106
+
107
+ #
108
+ # Run agent-specific metric setup, if necessary
109
+ setup_metrics if respond_to? :setup_metrics
110
+ end
111
+ def instance_label
112
+ if !respond_to? :instance_label_proc_method
113
+ mod=Module.new
114
+ mod.send :define_method,:instance_label_proc_method,self.class.instance_label_proc
115
+ self.extend mod
116
+ end
117
+ self.instance_label_proc_method
118
+ end
119
+
120
+ #
121
+ #
122
+ # Setup & Report Metrics
123
+ #
124
+ #
125
+ def report_metric metric_name,units,value,opts={}
126
+ return if value.nil?
127
+ @data_collector.add_data metric_name,units,value.to_f,opts
128
+ end
129
+
130
+ #
131
+ #
132
+ # Execute a poll cycle
133
+ #
134
+ #
135
+ def run poll_interval
136
+ #
137
+ # Start of cycle work, if any
138
+ cycle_start if respond_to? :cycle_start
139
+
140
+ #
141
+ # Collect Data
142
+ @data_collector=DataCollector.new self,poll_interval
143
+ poll_cycle
144
+ cnt=@data_collector.process
145
+ @data_collector=nil
146
+
147
+ #
148
+ # End of cycle work, if any
149
+ cycle_end if respond_to? :cycle_end
150
+ cnt
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,84 @@
1
+ require 'yaml'
2
+ module NewRelic
3
+ module Plugin
4
+ #
5
+ #
6
+ # Process global config file for NewRelic. This is defined per execution environment.
7
+ #
8
+ # Author:: Lee Atchison <lee@newrelic.com>
9
+ # Copyright:: Copyright (c) 2012 New Relic, Inc.
10
+ #
11
+ # The system configuration can be accessed as a hash using this method. For example:
12
+ #
13
+ # NewRelic::Plugin::Config.config.options['xxx']
14
+ # or:
15
+ # NewRelic::Plugin::Config.config.newrelic['...']
16
+ # or:
17
+ # NewRelic::Plugin::Config.config.agents['...']
18
+ #
19
+ #
20
+ class Config
21
+ attr_reader :options
22
+ # Creates an instance of a configuration object, loading the configuration
23
+ # from the YAML configuration file. Note: this method should not be used
24
+ # directly, rather the global method +config+ should be referenced instead.
25
+ def initialize
26
+ @options = YAML::load(Config.config_yaml) if Config.config_yaml
27
+ @options = YAML.load_file(Config.config_file) unless @options
28
+ end
29
+
30
+ #
31
+ # Return a hash of NewRelic configuration information.
32
+ #
33
+ # Usage: NewRelic::Plugin::Config.config.newrelic[...]
34
+ #
35
+ def newrelic
36
+ @options["newrelic"]
37
+ end
38
+ #
39
+ # Return a hash of agent configuration information.
40
+ #
41
+ # Usage: NewRelic::Plugin::Config.config.agents[...]
42
+ #
43
+ def agents
44
+ @options["agents"]
45
+ end
46
+
47
+ #
48
+ # Set the name of the configuration file:
49
+ #
50
+ # NewRelic::Plugin::Config.config_file="lib/config.yml"
51
+ #
52
+ def self.config_file= config_file
53
+ @config_file=config_file
54
+ @config_yaml=nil
55
+ @instance=nil
56
+ end
57
+ def self.config_file
58
+ @config_file||="config/newrelic_plugin.yml"
59
+ end
60
+ #
61
+ # Set the content of the configuration as a YAML string
62
+ #
63
+ # NewRelic::Plugin::Config.config_yaml="newrelic:\n test: 2\n test2: four\nagents:\n test: 4\n test2: six\n"
64
+ #
65
+ def self.config_yaml= config_yaml
66
+ @config_yaml=config_yaml
67
+ @config_file=nil
68
+ @instance=nil
69
+ end
70
+ def self.config_yaml
71
+ @config_yaml
72
+ end
73
+ #
74
+ # Returns a memoized version of the configuration object.
75
+ #
76
+ def self.config
77
+ @instance||=NewRelic::Plugin::Config.new
78
+ end
79
+ end
80
+ end
81
+ end
82
+ def plugin_config
83
+ NewRelic::Plugin::Config.config
84
+ end
@@ -0,0 +1,67 @@
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
@@ -0,0 +1,22 @@
1
+ module NewRelic
2
+
3
+ # Standard Errors
4
+ #
5
+ # Author:: Lee Atchison <lee@newrelic.com>
6
+ # Copyright:: Copyright (c) 2012 New Relic, Inc.
7
+ #
8
+ module Plugin # :nodoc:
9
+ class AgentError<Exception;end
10
+ class NoAgents<Exception;end
11
+ class NoMetrics<Exception;end
12
+ class NewRelicCommError<Exception;end
13
+ class UnknownInstalledAgent<AgentError;end
14
+ class UnknownInstalledProcessor<AgentError;end
15
+ class CouldNotInitializeAgent<AgentError;end
16
+ class CouldNotInitializeProcessor<AgentError;end
17
+ class BadConfig<AgentError;end
18
+ class NoResultReturned<AgentError;end
19
+ class NoDataReturned<AgentError;end
20
+ class InvalidMetricValueType<AgentError;end
21
+ end
22
+ end
@@ -0,0 +1,67 @@
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