httperfrb 0.2.0 → 0.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.
- data/HISTORY.md +5 -0
- data/README.md +27 -9
- data/lib/{parser.rb → httperf/parser.rb} +63 -20
- data/lib/httperf/version.rb +3 -0
- data/lib/httperf.rb +11 -6
- metadata +12 -11
data/HISTORY.md
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
HTTPERF.rb
|
2
2
|
==========
|
3
3
|
|
4
|
-
### [Documentation](http://rubyops.github.com/httperfrb/doc/) | [Coverage](http://rubyops.github.com/httperfrb/coverage/)
|
4
|
+
### [Documentation](http://rubyops.github.com/httperfrb/doc/) | [Coverage](http://rubyops.github.com/httperfrb/coverage/) | [RSpec Out](https://github.com/rubyops/httperfrb/blob/master/RSPECOUT.md)
|
5
5
|
|
6
6
|
Simple Ruby interface for httperf.
|
7
7
|
|
@@ -10,28 +10,27 @@ Simple Ruby interface for httperf.
|
|
10
10
|
This currently needs a lot of work to be production ready. It's done more in a scripting style then a true solid application style.
|
11
11
|
|
12
12
|
|
13
|
-
|
14
|
-
### Installing 'httperf'
|
13
|
+
## Installing 'httperf'
|
15
14
|
|
16
15
|
Requires httperf, of course...
|
17
16
|
|
18
|
-
|
17
|
+
#### Mac
|
19
18
|
|
20
19
|
sudo port install httperf
|
21
20
|
|
22
|
-
|
21
|
+
#### Debian / Ubuntu
|
23
22
|
|
24
23
|
sudo apt-get install httperf
|
25
24
|
|
26
|
-
|
25
|
+
#### Redhat / CentOS
|
27
26
|
|
28
27
|
sudo yum install httperf
|
29
28
|
|
30
|
-
|
29
|
+
## Install
|
31
30
|
|
32
31
|
gem install httperfrb
|
33
32
|
|
34
|
-
|
33
|
+
## Usage - HTTPerf
|
35
34
|
|
36
35
|
Some basic usage examples.
|
37
36
|
|
@@ -49,7 +48,7 @@ Some basic usage examples.
|
|
49
48
|
puts perf.fork_out
|
50
49
|
end
|
51
50
|
|
52
|
-
|
51
|
+
### With HTTPerf::Parser
|
53
52
|
|
54
53
|
require 'httperf'
|
55
54
|
perf = HTTPerf.new( "server" => "host", "port" => 8080, "uri" => "/foo" )
|
@@ -60,6 +59,17 @@ Some basic usage examples.
|
|
60
59
|
|
61
60
|
puts HTTPerf::Parser.parse( HTTPerf.new( "server" => "host", "port" => 8080, "uri" => "/foo" ).run )
|
62
61
|
|
62
|
+
## Useage - HTTPerf::Parser
|
63
|
+
|
64
|
+
require 'httperf/parser'
|
65
|
+
|
66
|
+
# read result from a file, for example
|
67
|
+
puts HTTPerf.parse( File.open("httperf.out", "r").read )
|
68
|
+
|
69
|
+
# or verbose output
|
70
|
+
puts HTTPerf.parse( File.open("httperf_verbose.out", "r").read, true )
|
71
|
+
|
72
|
+
|
63
73
|
##### Parser Keys:
|
64
74
|
|
65
75
|
:command
|
@@ -114,3 +124,11 @@ Some basic usage examples.
|
|
114
124
|
:errors_other
|
115
125
|
|
116
126
|
|
127
|
+
##### Addtional Verbose Parser Keys:
|
128
|
+
|
129
|
+
:connection_time_75_pct
|
130
|
+
:connection_time_80_pct
|
131
|
+
:connection_time_85_pct
|
132
|
+
:connection_time_90_pct
|
133
|
+
:connection_time_95_pct
|
134
|
+
:connection_time_99_pct
|
@@ -1,3 +1,4 @@
|
|
1
|
+
#require 'parser/verbose'
|
1
2
|
class HTTPerf
|
2
3
|
|
3
4
|
# Parse httperf output to a [Hash]
|
@@ -5,14 +6,60 @@ class HTTPerf
|
|
5
6
|
# This can be used standalone or with HTTPerf results.
|
6
7
|
class Parser
|
7
8
|
|
9
|
+
attr_accessor :verbose
|
10
|
+
|
8
11
|
# @return [Hash] returns hash of parsed httperf output
|
9
12
|
# @param [String] raw httperf output
|
10
|
-
def self.parse raw
|
13
|
+
def self.parse raw, verbose=false
|
11
14
|
|
12
15
|
lines = raw.split("\n")
|
16
|
+
matches = {}
|
17
|
+
|
18
|
+
# for verbose matching
|
19
|
+
verbose_connection_lifetime = []
|
20
|
+
|
21
|
+
lines.each do |line|
|
22
|
+
|
23
|
+
if verbose and verbose_expression.match(line)
|
24
|
+
verbose_connection_lifetime.push($1)
|
25
|
+
next
|
26
|
+
end
|
27
|
+
|
28
|
+
matched = false
|
29
|
+
unless line.empty?
|
30
|
+
next if matched
|
31
|
+
expressions.each do |key,exp|
|
32
|
+
if exp.match(line) and $1
|
33
|
+
matches[key] = $1
|
34
|
+
matched = true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
13
39
|
|
40
|
+
unless verbose_connection_lifetime.empty?
|
41
|
+
percentiles.each do |percentile|
|
42
|
+
matches["connection_time_#{percentile}_pct".to_sym] = calculate_percentile(percentile, verbose_connection_lifetime)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if verbose
|
47
|
+
raise "mismatch error occurred" unless expressions.keys.count+percentiles.count == matches.keys.count
|
48
|
+
else
|
49
|
+
raise "mismatch error occurred" unless expressions.keys.count == matches.keys.count
|
50
|
+
end
|
51
|
+
return matches
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def self.verbose_expression
|
57
|
+
/^Connection lifetime = ([0-9]*?\.?[0-9]+)$/
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.expressions
|
14
61
|
# While this isn't the most efficent way of doing this, it's the most maintainable.
|
15
|
-
|
62
|
+
{
|
16
63
|
:command => /^(httperf .+)$/,
|
17
64
|
|
18
65
|
# Maximum connect burst length:
|
@@ -92,25 +139,21 @@ class HTTPerf
|
|
92
139
|
:errors_ftab_full => /^Errors: fd-unavail .+ ftab-full ([0-9]*?\.?[0-9]+) /,
|
93
140
|
:errors_other => /^Errors: fd-unavail .+ other ([0-9]*?\.?[0-9]+)/
|
94
141
|
}
|
95
|
-
|
96
|
-
matches = {}
|
142
|
+
end
|
97
143
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
111
|
-
end
|
112
|
-
raise "mismatch error occurred" unless expressions.keys.count == matches.keys.count
|
113
|
-
return matches
|
144
|
+
def self.percentiles
|
145
|
+
[ 75, 80, 85, 90, 95, 99 ]
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
def self.calculate_percentile percentile, values
|
150
|
+
values.sort!
|
151
|
+
values[percentile_index(percentile, values.count)]
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.percentile_index percentile, count
|
155
|
+
((count/100)*percentile)-1
|
114
156
|
end
|
115
157
|
end
|
116
158
|
end
|
159
|
+
|
data/lib/httperf.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# @author Joshua Mervine <joshua@mervine.net>
|
2
2
|
require 'open4'
|
3
|
-
require 'parser'
|
3
|
+
require 'httperf/parser'
|
4
|
+
require 'httperf/version'
|
4
5
|
class HTTPerf
|
5
|
-
# gem version
|
6
|
-
VERSION = "0.2.0"
|
7
6
|
|
8
7
|
# @return [Boolean] parse flag
|
9
|
-
attr_accessor :parse
|
8
|
+
attr_accessor :parse, :verbose
|
10
9
|
|
11
10
|
# availbe instance methods
|
12
11
|
@fork_out, @fork_err = ''
|
@@ -57,6 +56,8 @@ class HTTPerf
|
|
57
56
|
# - wsesslog
|
58
57
|
# - wset
|
59
58
|
def initialize options={}, path=nil
|
59
|
+
self.parse = options.delete("parse")
|
60
|
+
self.verbose = true if options.has_key?("verbose")
|
60
61
|
options.each_key do |k|
|
61
62
|
raise "'#{k}' is an invalid httperf param" unless params.keys.include?(k)
|
62
63
|
end
|
@@ -89,7 +90,7 @@ class HTTPerf
|
|
89
90
|
end
|
90
91
|
if status == 0
|
91
92
|
if @parse
|
92
|
-
return Parser.parse(out.join)
|
93
|
+
return Parser.parse(out.join, self.verbose)
|
93
94
|
else
|
94
95
|
return out.join
|
95
96
|
end
|
@@ -109,7 +110,7 @@ class HTTPerf
|
|
109
110
|
# return results of last fork
|
110
111
|
def fork_out
|
111
112
|
if @parse
|
112
|
-
return Parse.parse
|
113
|
+
return Parse.parse(@fork_out, self.parse)
|
113
114
|
else
|
114
115
|
return @fork_out
|
115
116
|
end
|
@@ -126,6 +127,10 @@ class HTTPerf
|
|
126
127
|
return "#{@command} #{options}"
|
127
128
|
end
|
128
129
|
|
130
|
+
def verbose
|
131
|
+
@verbose||false
|
132
|
+
end
|
133
|
+
|
129
134
|
private
|
130
135
|
# build commandline options string
|
131
136
|
def options
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: httperfrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-08-11 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &13320100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *13320100
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: simplecov
|
27
|
-
requirement: &
|
27
|
+
requirement: &13317140 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *13317140
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: yard
|
38
|
-
requirement: &
|
38
|
+
requirement: &13316620 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *13316620
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: open4
|
49
|
-
requirement: &
|
49
|
+
requirement: &13316040 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *13316040
|
58
58
|
description: Simple interface for calling httperf via ruby.
|
59
59
|
email:
|
60
60
|
- joshua@mervine.net
|
@@ -62,7 +62,8 @@ executables: []
|
|
62
62
|
extensions: []
|
63
63
|
extra_rdoc_files: []
|
64
64
|
files:
|
65
|
-
- lib/
|
65
|
+
- lib/httperf/version.rb
|
66
|
+
- lib/httperf/parser.rb
|
66
67
|
- lib/httperf.rb
|
67
68
|
- README.md
|
68
69
|
- HISTORY.md
|
@@ -81,7 +82,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
82
|
version: '0'
|
82
83
|
segments:
|
83
84
|
- 0
|
84
|
-
hash:
|
85
|
+
hash: 4261295427007759208
|
85
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
87
|
none: false
|
87
88
|
requirements:
|