haproxy2rpm 0.0.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.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/README.md +32 -0
- data/Rakefile +12 -0
- data/bin/haproxy2rpm +63 -0
- data/haproxy2rpm.gemspec +21 -0
- data/lib/haproxy2rpm/file_parser.rb +24 -0
- data/lib/haproxy2rpm/line_parser.rb +48 -0
- data/lib/haproxy2rpm/version.rb +3 -0
- data/lib/haproxy2rpm.rb +26 -0
- data/test/fixtures/haproxy.log +1 -0
- data/test/haproxy2pm_test.rb +46 -0
- data/test/test_helper.rb +5 -0
- metadata +103 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Push haproxy logs to newrelic rpm
|
2
|
+
This is useful for languages where newrelic does not provide an agent,
|
3
|
+
such as erlang or node.js based applications
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
* copy your newrelic.yml file to $HOME/.newrelic/newrelic.yml
|
8
|
+
* or set $NRCONFIG to point to your newrelic.yml file
|
9
|
+
|
10
|
+
## Running it
|
11
|
+
haproxy2rpm /path/to/logfile
|
12
|
+
|
13
|
+
## Analyzing it
|
14
|
+
|
15
|
+
At the moment, it only works with custom views
|
16
|
+
|
17
|
+
<verbatim>
|
18
|
+
<h3>Charts</h3>
|
19
|
+
<table width='100%'>
|
20
|
+
<tr>
|
21
|
+
<td>line_chart {% line_chart value:'average_value' title:'Test' metric:'Custom/HAProxy/response_times' %}</td>
|
22
|
+
</tr>
|
23
|
+
|
24
|
+
</table>
|
25
|
+
</verbatim/>
|
26
|
+
|
27
|
+
|
28
|
+
## Roadmap
|
29
|
+
|
30
|
+
* daemonize option
|
31
|
+
* syslog (udp maybe tcp) server with https://github.com/melito/em-syslog and then point HaProxy to that port. Why touch the disk if we don't have to?
|
32
|
+
* Figure out how to report rpms and response times so that they show up inside the newrelic application view and not only as a custom metric
|
data/Rakefile
ADDED
data/bin/haproxy2rpm
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
NEW_RELIC_CONFIG_PATH = File.join(ENV['HOME'], '.newrelic', 'newrelic.yml')
|
9
|
+
|
10
|
+
help = <<HELP
|
11
|
+
haproxy2rpm
|
12
|
+
|
13
|
+
Basic Command Line Usage:
|
14
|
+
haproxy2rpm <haproxy log file to parse>
|
15
|
+
|
16
|
+
Coniguration for newrelic is read from #{NEW_RELIC_CONFIG_PATH}
|
17
|
+
HELP
|
18
|
+
|
19
|
+
options = { :daemonize => false, :version => false }
|
20
|
+
|
21
|
+
opts = OptionParser.new do |opts|
|
22
|
+
opts.banner = help
|
23
|
+
opts.on("-D", "--daemonize", "Daemonize") do
|
24
|
+
options[:daemonize] = true
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-v", "--version", "Print the version number and exit") do
|
28
|
+
options[:version] = true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.parse!
|
33
|
+
|
34
|
+
require 'haproxy2rpm'
|
35
|
+
|
36
|
+
log_file = ARGV[0] || ''
|
37
|
+
|
38
|
+
if(options[:version])
|
39
|
+
puts "Haproxy2Rpm version: #{Haproxy2Rpm::VERSION}"
|
40
|
+
exit(0)
|
41
|
+
end
|
42
|
+
|
43
|
+
unless File.exists?(log_file)
|
44
|
+
puts 'please proivde a valid path to a haproxy log file'
|
45
|
+
puts ''
|
46
|
+
puts help
|
47
|
+
exit(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
unless File.exists?(NEW_RELIC_CONFIG_PATH)
|
51
|
+
puts "please copy your newrelic agent configuration to #{NEW_RELIC_CONFIG_PATH}"
|
52
|
+
exit(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
if(options[:daemonize])
|
56
|
+
puts 'dameon mode not implemented yet'
|
57
|
+
else
|
58
|
+
trap("SIGINT") {
|
59
|
+
Haproxy2Rpm.stop
|
60
|
+
exit(0)
|
61
|
+
}
|
62
|
+
Haproxy2Rpm.run(log_file)
|
63
|
+
end
|
data/haproxy2rpm.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "haproxy2rpm/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "haproxy2rpm"
|
7
|
+
s.version = Haproxy2Rpm::VERSION
|
8
|
+
s.authors = ["Patrick Huesler"]
|
9
|
+
s.email = ["patrick.huesler@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = "Sending haproxy logs to new relic rpm"
|
12
|
+
s.description = "Sending haproxy logs to new relic rpm"
|
13
|
+
s.add_dependency "newrelic_rpm"
|
14
|
+
s.add_dependency "eventmachine-tail"
|
15
|
+
s.add_development_dependency "shoulda-context"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Haproxy2Rpm
|
2
|
+
class FileParser
|
3
|
+
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(path)
|
7
|
+
@lines = File.open(path){|f| f.readlines}
|
8
|
+
@records = []
|
9
|
+
@lines.each do |line|
|
10
|
+
@records << LineParser.new(line)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](element)
|
15
|
+
@records
|
16
|
+
end
|
17
|
+
|
18
|
+
def each &block
|
19
|
+
@records.each do |record|
|
20
|
+
yield record
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Haproxy2Rpm
|
2
|
+
class LineParser
|
3
|
+
|
4
|
+
def initialize(line)
|
5
|
+
@line = line
|
6
|
+
@parts = line.split("\s")
|
7
|
+
end
|
8
|
+
|
9
|
+
def tq
|
10
|
+
@tw ||= response_times[0].to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
def tw
|
14
|
+
@tw ||= response_times[1].to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def tc
|
18
|
+
@tc ||= response_times[2].to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def tr
|
22
|
+
@tr ||= response_times[3].to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
def tt
|
26
|
+
@tt ||= response_times[4].to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
def status_code
|
30
|
+
@status_code ||= @parts[6].to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
# we need to chop \"
|
34
|
+
def http_method
|
35
|
+
@http_method ||= @parts[13][1..-1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def uri
|
39
|
+
@uri ||= @parts[14]
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def response_times
|
45
|
+
@response_times ||= @parts[5].split("/")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/haproxy2rpm.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
require "newrelic_rpm"
|
4
|
+
require "eventmachine"
|
5
|
+
require "eventmachine-tail"
|
6
|
+
require "haproxy2rpm/version"
|
7
|
+
require "haproxy2rpm/file_parser"
|
8
|
+
require "haproxy2rpm/line_parser"
|
9
|
+
|
10
|
+
module Haproxy2Rpm
|
11
|
+
def self.run(log_file)
|
12
|
+
NewRelic::Agent.manual_start
|
13
|
+
stats_engine = NewRelic::Agent.agent.stats_engine
|
14
|
+
EventMachine.run do
|
15
|
+
EventMachine::file_tail(log_file) do |filetail, line|
|
16
|
+
request = LineParser.new(line)
|
17
|
+
stats_engine.get_stats('Custom/HAProxy/response_times',false).record_data_point(request.tr)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.stop
|
23
|
+
puts 'stopping new relic agent'
|
24
|
+
NewRelic::Agent.shutdown
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 6559/0/7/147/6723 200 243 - - ---- 1/3/5 0/0 "HEAD / HTTP/1.0"
|
@@ -0,0 +1,46 @@
|
|
1
|
+
$LOAD_PATH.unshift( File.dirname(__FILE__) )
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class Haproxy2RpmTest < Test::Unit::TestCase
|
6
|
+
context 'parsing of haproxy files' do
|
7
|
+
setup do
|
8
|
+
@line = File.open(File.join(File.dirname(__FILE__), 'fixtures', 'haproxy.log')){|f| f.readlines}.first
|
9
|
+
@result = Haproxy2Rpm::LineParser.new(@line)
|
10
|
+
end
|
11
|
+
|
12
|
+
should 'parse the Tq (total time in ms spent waiting for client)' do
|
13
|
+
assert_equal 6559, @result.tq
|
14
|
+
end
|
15
|
+
|
16
|
+
# this is the time waiting in the global queue
|
17
|
+
should 'parse the Tw (total time in ms spent waiting in queue)' do
|
18
|
+
assert_equal 0, @result.tw
|
19
|
+
end
|
20
|
+
|
21
|
+
should 'parse the Tc (total time in ms spent waiting for the connection to the final server' do
|
22
|
+
assert_equal 7, @result.tc
|
23
|
+
end
|
24
|
+
|
25
|
+
# this is the response time of your application server
|
26
|
+
should 'parse the Tr (total time in ms spent waiting for server to send full HTTP response)' do
|
27
|
+
assert_equal 147, @result.tr
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'parse the Tt (total time in ms spent between accept and close' do
|
31
|
+
assert_equal 6723, @result.tt
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'parse the status code' do
|
35
|
+
assert_equal 200, @result.status_code
|
36
|
+
end
|
37
|
+
|
38
|
+
should 'parse the http method' do
|
39
|
+
assert_equal 'HEAD', @result.http_method
|
40
|
+
end
|
41
|
+
|
42
|
+
should 'parse the uri' do
|
43
|
+
assert_equal '/', @result.uri
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: haproxy2rpm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Patrick Huesler
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-07-08 00:00:00 +02:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: newrelic_rpm
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: eventmachine-tail
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: shoulda-context
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id003
|
49
|
+
description: Sending haproxy logs to new relic rpm
|
50
|
+
email:
|
51
|
+
- patrick.huesler@gmail.com
|
52
|
+
executables:
|
53
|
+
- haproxy2rpm
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
58
|
+
files:
|
59
|
+
- .gitignore
|
60
|
+
- Gemfile
|
61
|
+
- README.md
|
62
|
+
- Rakefile
|
63
|
+
- bin/haproxy2rpm
|
64
|
+
- haproxy2rpm.gemspec
|
65
|
+
- lib/haproxy2rpm.rb
|
66
|
+
- lib/haproxy2rpm/file_parser.rb
|
67
|
+
- lib/haproxy2rpm/line_parser.rb
|
68
|
+
- lib/haproxy2rpm/version.rb
|
69
|
+
- test/fixtures/haproxy.log
|
70
|
+
- test/haproxy2pm_test.rb
|
71
|
+
- test/test_helper.rb
|
72
|
+
has_rdoc: true
|
73
|
+
homepage: ""
|
74
|
+
licenses: []
|
75
|
+
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: "0"
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: "0"
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.6.2
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: Sending haproxy logs to new relic rpm
|
100
|
+
test_files:
|
101
|
+
- test/fixtures/haproxy.log
|
102
|
+
- test/haproxy2pm_test.rb
|
103
|
+
- test/test_helper.rb
|