evidence 0.0.2 → 0.0.3
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/lib/evidence/log_parser.rb +0 -4
- data/lib/evidence/stream.rb +113 -42
- data/lib/evidence.rb +11 -56
- metadata +2 -2
data/lib/evidence/log_parser.rb
CHANGED
data/lib/evidence/stream.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
module Evidence
|
2
|
-
module
|
2
|
+
module Stream
|
3
|
+
include Enumerable
|
4
|
+
|
3
5
|
def |(process)
|
4
|
-
|
6
|
+
case process
|
7
|
+
when SliceStream
|
8
|
+
process.slice(self)
|
9
|
+
else
|
10
|
+
PipeStream.new(self, process)
|
11
|
+
end
|
5
12
|
end
|
6
13
|
end
|
7
14
|
|
8
|
-
|
9
|
-
|
10
|
-
class Stream
|
11
|
-
include Enumerable
|
12
|
-
include Pipeline
|
15
|
+
class PipeStream
|
16
|
+
include Stream
|
13
17
|
|
14
18
|
def initialize(upstream, process)
|
15
19
|
@upstream, @process = upstream, process
|
@@ -24,49 +28,34 @@ module Evidence
|
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
|
-
class
|
28
|
-
include
|
29
|
-
include Pipeline
|
31
|
+
class EnumStream
|
32
|
+
include Stream
|
30
33
|
|
31
|
-
def initialize(
|
32
|
-
@
|
34
|
+
def initialize(enum)
|
35
|
+
@enum = enum
|
33
36
|
end
|
34
37
|
|
35
38
|
def eos?
|
36
|
-
@
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
@file.each(&output)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class ArrayStream
|
45
|
-
include Enumerable
|
46
|
-
include Pipeline
|
47
|
-
|
48
|
-
def initialize(array)
|
49
|
-
@array = array
|
50
|
-
end
|
51
|
-
|
52
|
-
def eos?
|
53
|
-
@array.empty?
|
39
|
+
@enum.peek
|
40
|
+
false
|
41
|
+
rescue StopIteration
|
42
|
+
true
|
54
43
|
end
|
55
44
|
|
56
45
|
def each(&output)
|
57
|
-
|
58
|
-
output.
|
46
|
+
loop do
|
47
|
+
output[@enum.next]
|
59
48
|
end
|
49
|
+
rescue StopIteration
|
60
50
|
end
|
61
51
|
|
62
52
|
def to_s
|
63
|
-
"$[#{@
|
53
|
+
"$[#{@enum.inspect}]"
|
64
54
|
end
|
65
55
|
end
|
66
56
|
|
67
57
|
class MergedStream
|
68
|
-
include
|
69
|
-
include Pipeline
|
58
|
+
include Stream
|
70
59
|
|
71
60
|
def initialize(streams, comparator)
|
72
61
|
@comparator = comparator
|
@@ -103,22 +92,104 @@ module Evidence
|
|
103
92
|
end
|
104
93
|
end
|
105
94
|
|
106
|
-
class
|
107
|
-
include
|
108
|
-
include Pipeline
|
95
|
+
class SlicedStreams
|
96
|
+
include Stream
|
109
97
|
|
110
|
-
def initialize
|
111
|
-
@
|
98
|
+
def initialize(stream, index, start_index, end_index)
|
99
|
+
@stream, @index, @start_index, @end_index = stream, index, start_index, end_index
|
100
|
+
@slice_start_index, @slice_end_index = nil
|
112
101
|
end
|
113
102
|
|
114
103
|
def eos?
|
115
|
-
|
104
|
+
@stream.eos?
|
116
105
|
end
|
117
106
|
|
118
107
|
def each(&output)
|
108
|
+
return if eos?
|
109
|
+
@head ||= @stream.first
|
110
|
+
@slice_start_index ||= @start_index || @index[@head]
|
111
|
+
@slice_end_index ||= @end_index[@slice_start_index]
|
112
|
+
@eos_in_slice ||= false
|
113
|
+
loop do
|
114
|
+
if @slice_start_index > @index[@head]
|
115
|
+
return if eos?
|
116
|
+
@head = @stream.first
|
117
|
+
else
|
118
|
+
break
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
119
122
|
loop do
|
120
|
-
|
123
|
+
break if @eos_in_slice
|
124
|
+
range = @slice_start_index..@slice_end_index
|
125
|
+
slice_enum = Enumerator.new do |y|
|
126
|
+
loop do
|
127
|
+
break if range.max <= @index[@head]
|
128
|
+
if @eos_in_slice = eos?
|
129
|
+
y << @head
|
130
|
+
break
|
131
|
+
end
|
132
|
+
head, @head = @head, @stream.first
|
133
|
+
y << head
|
134
|
+
end
|
135
|
+
end
|
136
|
+
@slice_start_index, @slice_end_index = range.max, @end_index[range.max]
|
137
|
+
output[range, EnumStream.new(slice_enum)]
|
121
138
|
end
|
122
139
|
end
|
123
140
|
end
|
141
|
+
|
142
|
+
class SliceStream
|
143
|
+
def initialize(index, start_index, end_index)
|
144
|
+
@index, @start_index, @end_index = index, start_index, end_index
|
145
|
+
end
|
146
|
+
|
147
|
+
def slice(stream)
|
148
|
+
SlicedStreams.new(stream, @index, @start_index, @end_index)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
module_function
|
153
|
+
def stream(obj)
|
154
|
+
EnumStream.new(obj.to_enum)
|
155
|
+
end
|
156
|
+
|
157
|
+
def merge_streams(streams, comparator)
|
158
|
+
loop do
|
159
|
+
s1 = streams.shift
|
160
|
+
return s1 if streams.empty?
|
161
|
+
s2 = streams.shift
|
162
|
+
streams << MergedStream.new([s1, s2], comparator)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def slice_stream(index, step, start_index=nil)
|
167
|
+
end_index = step.is_a?(Proc) ? step : lambda { |index| index + step }
|
168
|
+
SliceStream.new(index, start_index, end_index)
|
169
|
+
end
|
170
|
+
|
171
|
+
def stream_each(&block)
|
172
|
+
lambda do |output|
|
173
|
+
lambda do |i|
|
174
|
+
block[i]
|
175
|
+
output[i]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def stream_map(&block)
|
181
|
+
lambda { |output| lambda { |i| output[block[i]] } }
|
182
|
+
end
|
183
|
+
|
184
|
+
def stream_filter(&block)
|
185
|
+
lambda { |output| lambda { |i| output[i] if block[i] } }
|
186
|
+
end
|
187
|
+
alias :stream_select :stream_filter
|
188
|
+
|
189
|
+
def counter
|
190
|
+
count = 0
|
191
|
+
counter = Enumerator.new { |y| loop { y << (count += 1) } }
|
192
|
+
stream(counter)
|
193
|
+
end
|
194
|
+
|
124
195
|
end
|
data/lib/evidence.rb
CHANGED
@@ -5,53 +5,9 @@ require 'evidence/rails_action_parser'
|
|
5
5
|
module Evidence
|
6
6
|
module_function
|
7
7
|
|
8
|
-
# convert Array or File object to a stream
|
9
|
-
def stream(obj)
|
10
|
-
case obj
|
11
|
-
when Array
|
12
|
-
ArrayStream.new(obj)
|
13
|
-
when File
|
14
|
-
FileStream.new(obj)
|
15
|
-
else
|
16
|
-
raise "Unknown how to convert #{obj.class} to a stream"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def merge_streams(streams, comparator)
|
21
|
-
loop do
|
22
|
-
s1 = streams.shift
|
23
|
-
return s1 if streams.empty?
|
24
|
-
s2 = streams.shift
|
25
|
-
streams << MergedStream.new([s1, s2], comparator)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def slice_stream(index, step, start_index=nil)
|
30
|
-
end_index = step.is_a?(Proc) ? step : lambda { |index| index + step }
|
31
|
-
lambda do |output|
|
32
|
-
@cache ||= []
|
33
|
-
start_index ||= @cache.first ? index[@cache.first] : nil
|
34
|
-
lambda do |log|
|
35
|
-
next_index = index[log]
|
36
|
-
start_index = index[log] if start_index.nil?
|
37
|
-
return if start_index > next_index
|
38
|
-
@cache << log
|
39
|
-
if end_index[start_index] <= next_index
|
40
|
-
range = start_index..end_index[start_index]
|
41
|
-
start_index = range.max
|
42
|
-
output.call(range, @cache.shift(@cache.size - 1))
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def counter
|
49
|
-
Counter.new
|
50
|
-
end
|
51
|
-
|
52
8
|
# Parse log file stream by given pattern
|
53
9
|
# pattern: ruby regex expression, has named group specified
|
54
|
-
#
|
10
|
+
# unmatched processor: process all unmatched log
|
55
11
|
def log_parser(pattern, unmatched=default_unmatched_process)
|
56
12
|
LogParser.new(pattern, unmatched)
|
57
13
|
end
|
@@ -66,11 +22,8 @@ module Evidence
|
|
66
22
|
# Rails action request timestamp parser
|
67
23
|
# log stream | rails_action_parser(pid, message) | request_timestamp_parser
|
68
24
|
def request_timestamp_parser(format="%Y-%m-%d %H:%M:%S")
|
69
|
-
|
70
|
-
|
71
|
-
action[:request][:timestamp] = Time.strptime(action[:request][:timestamp], format)
|
72
|
-
output[action]
|
73
|
-
end
|
25
|
+
stream_each do |action|
|
26
|
+
action[:request][:timestamp] = Time.strptime(action[:request][:timestamp], format)
|
74
27
|
end
|
75
28
|
end
|
76
29
|
|
@@ -79,12 +32,14 @@ module Evidence
|
|
79
32
|
# log stream | rails_action_parser(pid, message) | request_timestamp_parser | slice_stream(lambda {|action| action[:request][:timestamp]}, 60) | littles_law_analysis
|
80
33
|
def littles_law_analysis
|
81
34
|
lambda do |output|
|
82
|
-
lambda do |range,
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
35
|
+
lambda do |range, actions|
|
36
|
+
statistics = actions.inject(sum: 0, count: 0) do |memo, action|
|
37
|
+
memo[:count] += 1
|
38
|
+
memo[:sum] += action[:response][:completed_time].to_i
|
39
|
+
memo
|
40
|
+
end
|
41
|
+
avg_sec_arrival_rate = statistics[:count].to_f/(range.max - range.min)
|
42
|
+
avg_sec_response_time = statistics[:sum].to_f / statistics[:count] /1000
|
88
43
|
output[range, avg_sec_arrival_rate * avg_sec_response_time]
|
89
44
|
end
|
90
45
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: evidence
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-08-
|
13
|
+
date: 2013-08-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|