newrelic_haproxy_agent 0.0.5

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.
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ ## New Relic Haproxy Extension
2
+
3
+ ### Instructions for running the Haproxy extension agent
4
+
5
+ 1. run `bundle install` to install required gems
6
+ 2. Copy `config/newrelic_plugin.yml.example` to `config/newrelic_plugin.yml`
7
+ 3. Edit `config/newrelic_plugin.yml` and replace "YOUR_LICENSE_KEY_HERE" with your New Relic license key
8
+ 4. Edit the `config/newrelic_plugin.yml` file and add the URI of the haproxy CSV stats url
9
+ 5. Execute `ruby newrelic_haproxy_agent.rb`
10
+ 6. Go back to the Extensions list and after a brief period you will see the extension listed
data/Rakefile ADDED
@@ -0,0 +1,153 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
30
+ end
31
+
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
39
+
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
45
+
46
+ task :default => :test
47
+
48
+ require 'rake/testtask'
49
+ Rake::TestTask.new(:test) do |test|
50
+ test.libs << 'lib' << 'test'
51
+ test.pattern = 'test/**/test_*.rb'
52
+ test.verbose = true
53
+ end
54
+
55
+ desc "Generate RCov test coverage and open in your browser"
56
+ task :coverage do
57
+ require 'rcov'
58
+ sh "rm -fr coverage"
59
+ sh "rcov test/test_*.rb"
60
+ sh "open coverage/index.html"
61
+ end
62
+
63
+ require 'rdoc/task'
64
+ Rake::RDocTask.new do |rdoc|
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = "#{name} #{version}"
67
+ rdoc.rdoc_files.include('lib/**/*.rb')
68
+ rdoc.rdoc_files.include('README.rdoc')
69
+ rdoc.rdoc_files.include('LICENSE')
70
+ rdoc.rdoc_files.include('CHANGES')
71
+ rdoc.main = "README.rdoc"
72
+ end
73
+
74
+ desc "Open an irb session preloaded with this library"
75
+ task :console do
76
+ sh "irb -rubygems -r ./lib/#{name}.rb"
77
+ end
78
+
79
+ #############################################################################
80
+ #
81
+ # Custom tasks (add your own tasks here)
82
+ #
83
+ #############################################################################
84
+
85
+
86
+
87
+ #############################################################################
88
+ #
89
+ # Packaging tasks
90
+ #
91
+ #############################################################################
92
+
93
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
94
+ task :release => :build do
95
+ unless `git branch` =~ /^\* master$/
96
+ puts "You must be on the master branch to release!"
97
+ exit!
98
+ end
99
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
100
+ sh "git tag v#{version}"
101
+ sh "git push origin master"
102
+ sh "git push origin v#{version}"
103
+ sh "gem push pkg/#{name}-#{version}.gem"
104
+ end
105
+
106
+ desc "Build #{gem_file} into the pkg directory"
107
+ task :build => :gemspec do
108
+ sh "mkdir -p pkg"
109
+ sh "gem build #{gemspec_file}"
110
+ sh "mv #{gem_file} pkg"
111
+ end
112
+
113
+ desc "Generate #{gemspec_file}"
114
+ task :gemspec => :validate do
115
+ # read spec file and split out manifest section
116
+ spec = File.read(gemspec_file)
117
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
118
+
119
+ # replace name version and date
120
+ replace_header(head, :name)
121
+ replace_header(head, :version)
122
+ replace_header(head, :date)
123
+ #comment this out if your rubyforge_project has a different name
124
+ #replace_header(head, :rubyforge_project)
125
+
126
+ # determine file list from git ls-files
127
+ files = `git ls-files`.
128
+ split("\n").
129
+ sort.
130
+ reject { |file| file =~ /^\./ }.
131
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
132
+ map { |file| " #{file}" }.
133
+ join("\n")
134
+
135
+ # piece file back together and write
136
+ manifest = " s.files = %w[\n#{files}\n ]\n"
137
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
138
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
139
+ puts "Updated #{gemspec_file}"
140
+ end
141
+
142
+ desc "Validate #{gemspec_file}"
143
+ task :validate do
144
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
145
+ unless libfiles.empty?
146
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
147
+ exit!
148
+ end
149
+ unless Dir['VERSION*'].empty?
150
+ puts "A `VERSION` file at root level violates Gem best practices."
151
+ exit!
152
+ end
153
+ end
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ $stdout.sync = true
3
+
4
+ $LOAD_PATH.unshift File.expand_path "../../lib", __FILE__
5
+ require "newrelic_haproxy_agent"
6
+ require 'optparse'
7
+
8
+ NewRelic::Plugin::Config.config_file = "/etc/newrelic/newrelic_haproxy_agent.yml"
9
+
10
+ options = OptionParser.new do |opts|
11
+ opts.banner = <<-EOF
12
+ Usage:
13
+ newrelic_haproxy_agent ( run | install ) [options]
14
+ EOF
15
+
16
+ opts.on("-v", "--verbose", "Run verbosely") do
17
+ NewRelic::Plugin::Config.config.newrelic['verbose'] = 1
18
+ end
19
+
20
+ opts.on("-c", "--config FILE", "Override the location of the newrelic_plugin.yml") do | filename |
21
+ if !File.exists? filename
22
+ puts "File not found: #{filename.inspect}"
23
+ exit 1
24
+ end
25
+ NewRelic::Plugin::Config.config_file = filename
26
+ end
27
+
28
+ opts.on("-h", "--help") do
29
+ puts opts
30
+ if File.basename($0) == File.basename(__FILE__)
31
+ exit 0
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ args = options.parse!(ARGV)
38
+
39
+ if args.first == "run"
40
+ NewRelicHaproxyAgent.run
41
+ elsif args.first == "install"
42
+ config_file = File.read(File.expand_path("../../config/newrelic_plugin.yml.example", __FILE__))
43
+
44
+ require 'fileutils'
45
+ FileUtils.mkdir_p "/etc/newrelic"
46
+ File.open("/etc/newrelic/newrelic_haproxy_agent.yml", "w") do | io |
47
+ io.write(config_file)
48
+ end
49
+ puts "Saved agent config file #{File.expand_path("/etc/newrelic/newrelic_haproxy_agent.yml")}"
50
+ else
51
+ puts options
52
+ end
@@ -0,0 +1,50 @@
1
+ #
2
+ #
3
+ # This is a sample newrelic_plugin.yml file. Please move this file
4
+ # to the following location if it is not already there:
5
+ #
6
+ # ./config/newrelic_plugin.yml
7
+ #
8
+ # Where the current directory is the directory where your main program resides and is your current
9
+ # directory when you run the main program.
10
+ #
11
+ # Please make sure to update the license_key information with the license key for your New Relic
12
+ # account.
13
+ #
14
+ #
15
+ newrelic:
16
+ #
17
+ # Update with your New Relic account license key:
18
+ #
19
+ license_key: 'YOUR_LICENSE_KEY_HERE'
20
+ #
21
+ # Set to '1' for verbose output, remove for normal output.
22
+ # All output goes to stdout/stderr.
23
+ #
24
+ verbose: 1
25
+ #
26
+ # Agent Configuration:
27
+ #
28
+ agents:
29
+ my_haproxy_1:
30
+ # URI of the haproxy CSV stats url. See the 'CSV Export' link on your haproxy stats page (example stats page: http://demo.1wt.eu/).
31
+ uri: http://demo.1wt.eu/;csv
32
+ # The name of the proxy to monitor. Proxies are typically listed in the haproxy.cfg file.
33
+ proxy: http-in
34
+ # If multiple proxies have the same name, specify which proxy you want to monitor (ex: 'frontend' or 'backend')."
35
+ proxy_type: FRONTEND
36
+ # If protected under basic authentication provide the user name
37
+ user:
38
+ # If protected under basic authentication provide the password.
39
+ password:
40
+ my_haproxy_2:
41
+ # URI of the haproxy CSV stats url. See the 'CSV Export' link on your haproxy stats page (example stats page: http://demo.1wt.eu/).
42
+ uri: http://demo.1wt.eu/;csv
43
+ # The name of the proxy to monitor. Proxies are typically listed in the haproxy.cfg file.
44
+ proxy: www
45
+ # If multiple proxies have the same name, specify which proxy you want to monitor (ex: 'frontend' or 'backend')."
46
+ proxy_type: BACKEND
47
+ # If protected under basic authentication provide the user name
48
+ user:
49
+ # If protected under basic authentication provide the password.
50
+ password:
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+ require "newrelic_plugin"
6
+
7
+ if RUBY_VERSION < "1.9"
8
+ require 'fastercsv'
9
+ else
10
+ # typically, avoid require. In this case we can't use needs' deferred loading because we need to alias CSV
11
+ require 'csv'
12
+ FasterCSV=CSV
13
+ end
14
+ require 'open-uri'
15
+
16
+ module NewRelicHaproxyAgent
17
+
18
+ VERSION = '0.0.5'
19
+
20
+ class Agent < NewRelic::Plugin::Agent::Base
21
+
22
+ agent_guid "com.railsware.haproxy"
23
+ agent_config_options :uri, :proxy, :proxy_type, :user, :password
24
+ agent_version NewRelicHaproxyAgent::VERSION
25
+ agent_human_labels("Haproxy") { ident }
26
+
27
+ attr_reader :ident
28
+
29
+ def setup_metrics
30
+ @requests=NewRelic::Processor::EpochCounter.new
31
+ @errors_req=NewRelic::Processor::EpochCounter.new
32
+ @errors_conn=NewRelic::Processor::EpochCounter.new
33
+ @errors_resp=NewRelic::Processor::EpochCounter.new
34
+ @bytes_in=NewRelic::Processor::EpochCounter.new
35
+ @bytes_out=NewRelic::Processor::EpochCounter.new
36
+ end
37
+
38
+ def poll_cycle
39
+ if uri.nil?
40
+ raise("URI to HAProxy Stats Required It looks like the URI to the HAProxy stats page (in csv format) hasn't been provided. Please enter this URI in the plugin settings.")
41
+ end
42
+ if proxy_type
43
+ if proxy_type =~ /frontend|backend/i
44
+ @proxy_type = proxy_type.upcase
45
+ end
46
+ end
47
+ found_proxies = []
48
+ possible_proxies = []
49
+ begin
50
+ FasterCSV.parse(open(uri, :http_basic_authentication => [user, password]), :headers => true) do |row|
51
+ next if proxy_type and proxy_type != row["svname"] # ensure the proxy type (if provided) matches
52
+ possible_proxies << row["# pxname"] # used in error message
53
+ next unless proxy.to_s.strip.downcase == row["# pxname"].downcase # ensure the proxy name matches
54
+ # if multiple proxies have the same name, we don't know which to report on.
55
+ if found_proxies.include?(row["# pxname"])
56
+ raise("Multiple proxies have the name '#{proxy}'. Please specify the proxy type (ex: BACKEND or FRONTEND) in the plugin's settings.")
57
+ end
58
+ found_proxies << row["# pxname"]
59
+
60
+ report_metric "Requests", "Requests/Minute", @requests.process(row['stot'].to_i) * 60 if @requests.process(row['stot'].to_i)
61
+ report_metric "Errors/Request", "Errors/Minute", @errors_req.process(row['ereq'].to_i) * 60 if @errors_req.process(row['ereq'].to_i)
62
+ report_metric "Errors/Connection", "Errors/Minute", @errors_conn.process(row['econ'].to_i) * 60 if @errors_conn.process(row['econ'].to_i)
63
+ report_metric "Errors/Response", "Errors/Minute", @errors_resp.process(row['eresp'].to_i) * 60 if @errors_resp.process(row['eresp'].to_i)
64
+
65
+ report_metric "Bytes/Received", "Bytes/Seconds", @bytes_in.process(row['bin'].to_i)
66
+ report_metric "Bytes/Sent", "Bytes/Seconds", @bytes_out.process(row['bout'].to_i)
67
+
68
+ report_metric "Sessions/Active", "Sessions", row['scur']
69
+ report_metric "Sessions/Queued", "Sessions", row['qcur']
70
+ report_metric "Servers/Active", "Servers", row['act']
71
+ report_metric "Servers/Backup", "Servers", row['bck']
72
+ report_metric "ProxyUp", "Status", %w(UP OPEN).find {|s| s == row['status']} ? 1 : 0
73
+
74
+ end # FasterCSV.parse
75
+ rescue OpenURI::HTTPError
76
+ if $!.message == '401 Unauthorized'
77
+ raise("Authentication Failed. Unable to access the stats page at #{uri} with the username '#{user}' and provided password. Please ensure the username, password, and URI are correct.")
78
+ elsif $!.message != '404 Not Found'
79
+ raise("Unable to find the stats page. The stats page could not be found at: #{uri}.")
80
+ else
81
+ raise
82
+ end
83
+ rescue FasterCSV::MalformedCSVError
84
+ raise("Unable to access stats page. The plugin encountered an error attempting to access the stats page (in CSV format) at: #{uri}. The exception: #{$!.message}\n#{$!.backtrace}")
85
+ end
86
+ if proxy.nil?
87
+ raise("Proxy name required. The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor: #{possible_proxies.join(', ')}")
88
+ elsif found_proxies.empty?
89
+ raise("Proxy not found. The proxy '#{proxy}' #{proxy_type ? "w/proxy type [#{proxy_type}]" : nil} was not found. The possible proxies #{proxy_type ? "for this proxy type" : nil} to monitor: #{possible_proxies.join(', ')}")
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+
96
+ # Register and run the agent
97
+ def self.run
98
+ NewRelic::Plugin::Config.config.agents.keys.each do |agent|
99
+ NewRelic::Plugin::Setup.install_agent agent, NewRelicHaproxyAgent
100
+ end
101
+
102
+ #
103
+ # Launch the agent (never returns)
104
+ #
105
+ NewRelic::Plugin::Run.setup_and_run
106
+ end
107
+
108
+ end
@@ -0,0 +1,80 @@
1
+ ## This is the rakegem gemspec template. Make sure you read and understand
2
+ ## all of the comments. Some sections require modification, and others can
3
+ ## be deleted if you don't need them. Once you understand the contents of
4
+ ## this file, feel free to delete any comments that begin with two hash marks.
5
+ ## You can find comprehensive Gem::Specification documentation, at
6
+ ## http://docs.rubygems.org/read/chapter/20
7
+ Gem::Specification.new do |s|
8
+ s.specification_version = 2 if s.respond_to? :specification_version=
9
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.rubygems_version = '1.3.5'
11
+
12
+ ## Leave these as is they will be modified for you by the rake gemspec task.
13
+ ## If your rubyforge_project name is different, then edit it and comment out
14
+ ## the sub! line in the Rakefile
15
+ s.name = 'newrelic_haproxy_agent'
16
+ s.version = '0.0.5'
17
+ s.date = '2013-06-29'
18
+ # s.rubyforge_project = 'newrelic_haproxy_agent'
19
+
20
+ ## Make sure your summary is short. The description may be as long
21
+ ## as you like.
22
+ s.summary = "New Relic Haproxy monitoring plugin"
23
+ s.description = <<-EOF
24
+ This is the New Relic plugin for monitoring Haproxy developed by Railsware Inc.
25
+ EOF
26
+
27
+ ## List the primary authors. If there are a bunch of authors, it's probably
28
+ ## better to set the email to an email list or something. If you don't have
29
+ ## a custom homepage, consider using your GitHub URL or the like.
30
+ s.authors = ["Maxim Bondaruk"]
31
+ s.email = 'maxim.bondaruk@railsware.com'
32
+ s.homepage = 'https://github.com/railsware/newrelic_platform_plugins/tree/master/newrelic_haproxy_agent'
33
+
34
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
35
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
36
+ s.require_paths = %w[lib]
37
+
38
+ ## This sections is only necessary if you have C extensions.
39
+ #s.require_paths << 'ext'
40
+ #s.extensions = %w[ext/extconf.rb]
41
+
42
+ ## If your gem includes any executables, list them here.
43
+ s.executables = ["newrelic_haproxy_agent"]
44
+
45
+ ## Specify any RDoc options here. You'll want to add your README and
46
+ ## LICENSE files to the extra_rdoc_files list.
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.extra_rdoc_files = %w[README.md]
49
+
50
+ ## List your runtime dependencies here. Runtime dependencies are those
51
+ ## that are needed for an end user to actually USE your code.
52
+ s.add_dependency('newrelic_plugin', "1.0.3")
53
+ s.add_dependency('fastercsv', ">= 1.5.5") if RUBY_VERSION < "1.9"
54
+
55
+
56
+ s.post_install_message = <<-EOF
57
+ To get started with this plugin, do
58
+ newrelic_haproxy_agent -h
59
+ to find out how to install and run the plugin agent.
60
+ EOF
61
+
62
+ ## Leave this section as-is. It will be automatically generated from the
63
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
64
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
65
+ # = MANIFEST =
66
+ s.files = %w[
67
+ Gemfile
68
+ README.md
69
+ Rakefile
70
+ bin/newrelic_haproxy_agent
71
+ config/newrelic_plugin.yml.example
72
+ lib/newrelic_haproxy_agent.rb
73
+ newrelic_haproxy_agent.gemspec
74
+ ]
75
+ # = MANIFEST =
76
+
77
+ ## Test files will be grabbed from the file list. Make sure the path glob
78
+ ## matches what you actually use.
79
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
80
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: newrelic_haproxy_agent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Maxim Bondaruk
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: newrelic_plugin
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.3
30
+ description: ! 'This is the New Relic plugin for monitoring Haproxy developed by Railsware
31
+ Inc.
32
+
33
+ '
34
+ email: maxim.bondaruk@railsware.com
35
+ executables:
36
+ - newrelic_haproxy_agent
37
+ extensions: []
38
+ extra_rdoc_files:
39
+ - README.md
40
+ files:
41
+ - Gemfile
42
+ - README.md
43
+ - Rakefile
44
+ - bin/newrelic_haproxy_agent
45
+ - config/newrelic_plugin.yml.example
46
+ - lib/newrelic_haproxy_agent.rb
47
+ - newrelic_haproxy_agent.gemspec
48
+ homepage: https://github.com/railsware/newrelic_platform_plugins/tree/master/newrelic_haproxy_agent
49
+ licenses: []
50
+ post_install_message: ! " To get started with this plugin, do\n newrelic_haproxy_agent
51
+ -h\n to find out how to install and run the plugin agent.\n"
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.24
71
+ signing_key:
72
+ specification_version: 2
73
+ summary: New Relic Haproxy monitoring plugin
74
+ test_files: []