haproxy2rpm 0.0.10 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v 0.1.0
4
+
5
+ * Make Syslog parsing independent from haproxy
6
+ * Examples on how to use it with node.js and connect including a simple
7
+ node.js profiler
8
+
3
9
  ## v 0.0.10
4
10
 
5
11
  * Do not crash when an exception occurs during URI parsing (Knut
data/README.md CHANGED
@@ -27,6 +27,10 @@ Tell haproxy to log to syslog. e.g:
27
27
 
28
28
  Check the examples folder
29
29
 
30
+ ## Node.js support
31
+
32
+ Check the examples folder
33
+
30
34
  ## Supported RPM features
31
35
 
32
36
  * Response times in application server
@@ -46,6 +50,7 @@ Tested in production
46
50
 
47
51
  Passing manual integration test with test logs
48
52
 
53
+ * mri-1.9.3
49
54
  * mri-1.9.2-p180
50
55
  * ree-1.8.7-2011.03
51
56
  * mri-1.8.7-p33
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Profile the duration of a request.
3
+ *
4
+ * Example Output:
5
+ *
6
+ * GET / 200 2
7
+ *
8
+ *
9
+ * Example usage:
10
+ *
11
+ * npm install ain2
12
+ *
13
+ * var SysLogger = require('ain2');
14
+ * var profiler = require('./connect_middleware.js');
15
+ * app.use(profiler(new SysLogger({ tag : "newrelic", facility : 'local0' })));
16
+ *
17
+ *
18
+ * @api public
19
+ */
20
+ module.exports = function profiler(_logger){
21
+ return function(req, res, next){
22
+ var end = res.end
23
+ , start = new Date()
24
+ , logger = _logger || console;
25
+
26
+ // proxy res.end()
27
+ res.end = function(data, encoding){
28
+ res.end = end;
29
+ res.end(data, encoding);
30
+ logger.log(req.method, req.url, res.statusCode, ((new Date) - start));
31
+ };
32
+
33
+ next();
34
+ }
35
+ };
@@ -0,0 +1,72 @@
1
+ #
2
+ # Expected format: Method Uri Status Time
3
+ #
4
+ # GET /test 200 2
5
+ #
6
+ class NodeJsLineParser
7
+
8
+ def initialize(line)
9
+ @parts = line.split("\s")
10
+ end
11
+
12
+ def response_time
13
+ @response_time ||= @parts[3].to_i
14
+ end
15
+
16
+
17
+ def status_code
18
+ @status_code ||= @parts[2].to_i
19
+ end
20
+
21
+ def http_method
22
+ @http_method ||= @parts[0]
23
+ end
24
+
25
+ def uri
26
+ @uri ||= URI.parse(@parts[1])
27
+ end
28
+
29
+ def http_path
30
+ uri.path
31
+ end
32
+
33
+ def http_query
34
+ uri.query
35
+ end
36
+
37
+ def is_error?
38
+ status_code >= 500
39
+ end
40
+
41
+ end
42
+
43
+ config.message_parser = lambda do |line|
44
+ NodeJsLineParser.new(line)
45
+ end
46
+
47
+ config.request_recorder = lambda do |request|
48
+ rpm_number_unit = 1000.0
49
+ params = {
50
+ 'metric' => "Controller#{route_for(request.http_path)}"
51
+ }
52
+
53
+ if request.is_error?
54
+ params['is_error'] = true
55
+ params['error_message'] = "#{request.uri} : Status code #{request.status_code}"
56
+ end
57
+
58
+ record_transaction(request.response_time / rpm_number_unit, params)
59
+ Haproxy2Rpm.logger.debug "RECORDING (transaction) #{request.http_path}: #{params.inspect}"
60
+ end
61
+
62
+ config.routes = [
63
+ {
64
+ :pattern => %r{^/$},
65
+ :target => '/index'
66
+ },
67
+ {
68
+ :pattern => %r{(\.[a-zA-Z_]{2,4})$},
69
+ :target => '/static'
70
+ }
71
+ ]
72
+
@@ -2,13 +2,7 @@ module Haproxy2Rpm
2
2
  class LineParser
3
3
 
4
4
  def initialize(line)
5
- @line = line
6
-
7
- if @line.match "haproxy"
8
- @parts = @line.split("haproxy")[1].split("\s")
9
- else
10
- @parts = @line.split("\s")
11
- end
5
+ @parts = line.split("\s")
12
6
  end
13
7
 
14
8
  def tq
@@ -32,16 +26,16 @@ module Haproxy2Rpm
32
26
  end
33
27
 
34
28
  def status_code
35
- @status_code ||= @parts[6].to_i
29
+ @status_code ||= @parts[5].to_i
36
30
  end
37
31
 
38
32
  # we need to chop \"
39
33
  def http_method
40
- @http_method ||= @parts[13][1..-1]
34
+ @http_method ||= @parts[12][1..-1]
41
35
  end
42
36
 
43
37
  def uri
44
- @uri ||= URI.parse(@parts[14])
38
+ @uri ||= URI.parse(@parts[13])
45
39
  end
46
40
 
47
41
  def http_path
@@ -59,7 +53,7 @@ module Haproxy2Rpm
59
53
  private
60
54
 
61
55
  def response_times
62
- @response_times ||= @parts[5].split("/")
56
+ @response_times ||= @parts[4].split("/")
63
57
  end
64
58
  end
65
59
  end
@@ -1,12 +1,45 @@
1
1
  # Taken from
2
2
  # https://raw.github.com/jordansissel/experiments/master/ruby/eventmachine-speed/basic.rb
3
+ #
3
4
  module Haproxy2Rpm
4
5
  class SyslogHandler < EventMachine::Connection
6
+
7
+ def initialize(*args)
8
+ # The syslog parsing stuff here taken from the 'logporter' gem.
9
+ pri = "(?:<(?<pri>[0-9]{1,3})>)?"
10
+ month = "(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"
11
+ day = "(?: [1-9]|[12][0-9]|3[01])"
12
+ hour = "(?:[01][0-9]|2[0-4])"
13
+ minute = "(?:[0-5][0-9])"
14
+ second = "(?:[0-5][0-9])"
15
+ time = [hour, minute, second].join(":")
16
+ timestamp = "(?<timestamp>#{month} #{day} #{time})"
17
+ hostname = "(?<hostname>[A-Za-z0-9_.:]+)"
18
+ header = timestamp + " " + hostname
19
+ tag = '(?<tag>[a-zA-Z_\-\/\.0-9\[\]]+)'
20
+ message = "(?<message>[ -~]+)" # ascii 32 to 126
21
+ re = "^#{pri}#{header} #{tag}:\s*#{message}"
22
+
23
+ if RUBY_VERSION =~ /^1\.8/
24
+ # Ruby 1.8 doesn't support named captures
25
+ # replace (?<foo> with (
26
+ re = re.gsub(/\(\?<[^>]+>/, "(")
27
+ end
28
+
29
+ @syslog3164_re = Regexp.new(re)
30
+ end
31
+
5
32
  def receive_data(data)
6
- message_start_index = data.index('haproxy')
7
- message = data[message_start_index..-1]
8
- Haproxy2Rpm.logger.debug "RECEIVED (syslog): #{message}"
33
+ match = parse_data(data)
34
+ puts match.inspect
35
+ message = match ? match[5] : ""
36
+ Haproxy2Rpm.logger.debug "RECEIVED (syslog): #{data}"
9
37
  Haproxy2Rpm.rpm.process_and_send(message)
10
38
  end
39
+
40
+ def parse_data(data)
41
+ @syslog3164_re.match(data)
42
+ end
43
+
11
44
  end
12
45
  end
@@ -1,3 +1,3 @@
1
1
  module Haproxy2Rpm
2
- VERSION = "0.0.10"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,33 @@
1
+ $LOAD_PATH.unshift( File.dirname(__FILE__) )
2
+
3
+ require 'test_helper'
4
+
5
+ FIXTURE_SYSLOG_MESSAGE = "<12>Jan 3 16:18:58 rechenschieber.local nodejs[36180]: message"
6
+
7
+ class RpmTest < Test::Unit::TestCase
8
+ context 'regex maching' do
9
+ setup do
10
+ @match = Haproxy2Rpm::SyslogHandler.new(self).parse_data(FIXTURE_SYSLOG_MESSAGE)
11
+ end
12
+
13
+ should 'match the priority' do
14
+ assert_equal '12', @match[1]
15
+ end
16
+
17
+ should 'match timestamp' do
18
+ assert_equal "Jan 3 16:18:58", @match[2]
19
+ end
20
+
21
+ should 'match the hostname' do
22
+ assert_equal "rechenschieber.local", @match[3]
23
+ end
24
+
25
+ should 'match the tag name' do
26
+ assert_equal 'nodejs[36180]', @match[4]
27
+ end
28
+
29
+ should 'match the message' do
30
+ assert_equal 'message', @match[5]
31
+ end
32
+ end
33
+ end
data/test/test_helper.rb CHANGED
@@ -17,7 +17,7 @@ class DummyLogger
17
17
  end
18
18
  Haproxy2Rpm.logger = DummyLogger.new
19
19
 
20
- def log_entry(options = {})
20
+ def syslog_entry(options = {})
21
21
  defaults = {
22
22
  :tq => 6559,
23
23
  :tw => 100,
@@ -34,3 +34,21 @@ def log_entry(options = {})
34
34
  Aug 1 15:28:03 ip-10-58-122-30.eu-west-1.compute.internal haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 #{defaults[:tq]}/#{defaults[:tw]}/#{defaults[:tc]}/#{defaults[:tr]}/#{defaults[:tt]} #{defaults[:status_code]} 243 - - ---- 1/3/5 0/0 "#{defaults[:http_method]} #{defaults[:http_path]}#{defaults[:http_query] ? "?#{defaults[:http_query]}" : ''} HTTP/1.0"
35
35
  LOG_LINE
36
36
  end
37
+
38
+ def log_entry(options = {})
39
+ defaults = {
40
+ :tq => 6559,
41
+ :tw => 100,
42
+ :tc => 7,
43
+ :tr => 147,
44
+ :tt => 6723,
45
+ :status_code => 200,
46
+ :http_path => '/',
47
+ :http_method => 'GET',
48
+ :http_query => 'example_param=test',
49
+ }
50
+ defaults.merge!(options)
51
+ log_line = <<LOG_LINE
52
+ 127.0.0.1:33319 [15/Oct/2003:08:31:57] relais-http Srv1 #{defaults[:tq]}/#{defaults[:tw]}/#{defaults[:tc]}/#{defaults[:tr]}/#{defaults[:tt]} #{defaults[:status_code]} 243 - - ---- 1/3/5 0/0 "#{defaults[:http_method]} #{defaults[:http_path]}#{defaults[:http_query] ? "?#{defaults[:http_query]}" : ''} HTTP/1.0"
53
+ LOG_LINE
54
+ end
metadata CHANGED
@@ -1,81 +1,105 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: haproxy2rpm
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.10
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Patrick Huesler
9
14
  - Martin Rehfeld
10
15
  autorequire:
11
16
  bindir: bin
12
17
  cert_chain: []
13
- date: 2011-09-02 00:00:00.000000000 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
18
+
19
+ date: 2012-01-03 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
16
23
  name: newrelic_rpm
17
- requirement: &70241929478900 !ruby/object:Gem::Requirement
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
18
26
  none: false
19
- requirements:
20
- - - ! '>='
21
- - !ruby/object:Gem::Version
22
- version: '0'
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
23
34
  type: :runtime
24
- prerelease: false
25
- version_requirements: *70241929478900
26
- - !ruby/object:Gem::Dependency
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
27
37
  name: eventmachine-tail
28
- requirement: &70241929476180 !ruby/object:Gem::Requirement
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
29
40
  none: false
30
- requirements:
31
- - - ! '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
34
48
  type: :runtime
35
- prerelease: false
36
- version_requirements: *70241929476180
37
- - !ruby/object:Gem::Dependency
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
38
51
  name: rake
39
- requirement: &70241929470660 !ruby/object:Gem::Requirement
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
40
54
  none: false
41
- requirements:
42
- - - ! '>='
43
- - !ruby/object:Gem::Version
44
- version: '0'
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
45
62
  type: :development
46
- prerelease: false
47
- version_requirements: *70241929470660
48
- - !ruby/object:Gem::Dependency
63
+ version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
49
65
  name: shoulda-context
50
- requirement: &70241929468160 !ruby/object:Gem::Requirement
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
51
68
  none: false
52
- requirements:
53
- - - ! '>='
54
- - !ruby/object:Gem::Version
55
- version: '0'
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
56
76
  type: :development
57
- prerelease: false
58
- version_requirements: *70241929468160
59
- - !ruby/object:Gem::Dependency
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
60
79
  name: mocha
61
- requirement: &70241929467720 !ruby/object:Gem::Requirement
80
+ prerelease: false
81
+ requirement: &id005 !ruby/object:Gem::Requirement
62
82
  none: false
63
- requirements:
64
- - - ! '>='
65
- - !ruby/object:Gem::Version
66
- version: '0'
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
67
90
  type: :development
68
- prerelease: false
69
- version_requirements: *70241929467720
91
+ version_requirements: *id005
70
92
  description: Sending haproxy logs to new relic rpm
71
- email:
93
+ email:
72
94
  - patrick.huesler@wooga.com
73
95
  - martin.rehfeld@wooga.com
74
- executables:
96
+ executables:
75
97
  - haproxy2rpm
76
98
  extensions: []
99
+
77
100
  extra_rdoc_files: []
78
- files:
101
+
102
+ files:
79
103
  - .gitignore
80
104
  - .travis.yml
81
105
  - CHANGELOG.md
@@ -85,6 +109,8 @@ files:
85
109
  - Research.md
86
110
  - bin/haproxy2rpm
87
111
  - config/newrelic.yml.example
112
+ - examples/connect_middleware.js
113
+ - examples/connect_middleware_config.rb
88
114
  - examples/haproxy2rpm.monitrc
89
115
  - examples/routes.rb
90
116
  - examples/simple_config.rb
@@ -98,33 +124,45 @@ files:
98
124
  - test/fixtures/config.rb
99
125
  - test/haproxy2pm_test.rb
100
126
  - test/rpm_test.rb
127
+ - test/syslog_test.rb
101
128
  - test/test_helper.rb
129
+ has_rdoc: true
102
130
  homepage: https://github.com/wooga/haproxy2rpm
103
131
  licenses: []
132
+
104
133
  post_install_message:
105
134
  rdoc_options: []
106
- require_paths:
135
+
136
+ require_paths:
107
137
  - lib
108
- required_ruby_version: !ruby/object:Gem::Requirement
138
+ required_ruby_version: !ruby/object:Gem::Requirement
109
139
  none: false
110
- requirements:
111
- - - ! '>='
112
- - !ruby/object:Gem::Version
113
- version: '0'
114
- required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 3
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
148
  none: false
116
- requirements:
117
- - - ! '>='
118
- - !ruby/object:Gem::Version
119
- version: '0'
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ hash: 3
153
+ segments:
154
+ - 0
155
+ version: "0"
120
156
  requirements: []
157
+
121
158
  rubyforge_project:
122
- rubygems_version: 1.8.6
159
+ rubygems_version: 1.6.2
123
160
  signing_key:
124
161
  specification_version: 3
125
162
  summary: Sending haproxy logs to new relic rpm
126
- test_files:
163
+ test_files:
127
164
  - test/fixtures/config.rb
128
165
  - test/haproxy2pm_test.rb
129
166
  - test/rpm_test.rb
167
+ - test/syslog_test.rb
130
168
  - test/test_helper.rb