benelux 0.3.2 → 0.4.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.
@@ -18,18 +18,23 @@ module Benelux
18
18
  # regions = Benelux.timeline(track_id).regions(:execute)
19
19
  #
20
20
  class Timeline < Array
21
+ include Selectable
22
+
21
23
  attr_accessor :ranges
24
+ attr_accessor :counts
22
25
  attr_accessor :stats
23
26
  attr_accessor :default_tags
24
27
  attr_reader :caller
25
28
  def initialize(*args)
26
29
  @caller = Kernel.caller
27
- @ranges, @default_tags = [], Benelux::Tags.new
30
+ @counts = SelectableArray.new
31
+ @ranges = SelectableArray.new
32
+ @default_tags = Selectable::Tags.new
28
33
  @stats = Benelux::Stats.new
29
34
  add_default_tag :thread_id => Thread.current.object_id.abs
30
35
  super
31
36
  end
32
- def add_default_tags(tags=Benelux::Tags.new)
37
+ def add_default_tags(tags=Selectable::Tags.new)
33
38
  @default_tags.merge! tags
34
39
  end
35
40
  alias_method :add_default_tag, :add_default_tags
@@ -65,12 +70,8 @@ module Benelux
65
70
  end
66
71
  end
67
72
 
68
- def [](tags={})
69
- #tags = Benelux::TagHelpers.normalize tags
70
- marks = self.select do |mark|
71
- mark.tags >= tags
72
- end
73
- tl = Benelux::Timeline.new marks
73
+ def [](*tags)
74
+ tl = super
74
75
  tl.ranges = @ranges.select do |region|
75
76
  region.tags >= tags
76
77
  end
@@ -87,7 +88,7 @@ module Benelux
87
88
  # obj.ranges(:do_request) =>
88
89
  # [[:do_request_a, :do_request_z], [:do_request_a, ...]]
89
90
  #
90
- def ranges(name=nil, tags=Benelux::Tags.new)
91
+ def ranges(name=nil, tags=Selectable::Tags.new)
91
92
  return @ranges if name.nil?
92
93
  @ranges.select do |range|
93
94
  ret = name.to_s == range.name.to_s &&
@@ -96,11 +97,19 @@ module Benelux
96
97
  end
97
98
  end
98
99
 
100
+ def counts(name=nil, tags=Selectable::Tags.new)
101
+ return @counts if name.nil?
102
+ @counts.select do |count|
103
+ ret = name.to_s == count.name.to_s &&
104
+ (tags.nil? || count.tags >= tags)
105
+ ret
106
+ end
107
+ end
99
108
  #
100
- # obj.ranges(:do_request) =>
101
- # [[:do_request_a, :get_body, :do_request_z], [:do_request_a, ...]]
109
+ # obj.regions(:do_request) =>
110
+ #
102
111
  #
103
- def regions(name=nil, tags=Benelux::Tags.new)
112
+ def regions(name=nil, tags=Selectable::Tags.new)
104
113
  return self if name.nil?
105
114
  self.ranges(name, tags).collect do |base_range|
106
115
  marks = self.sort.select do |mark|
@@ -124,46 +133,47 @@ module Benelux
124
133
  super
125
134
  end
126
135
 
136
+ # TODO: Remove Benelux::Count. Just use Stats!
137
+ def add_count(name, count, tags={})
138
+ tags = tags.merge self.default_tags
139
+ c = Benelux::Count.new(name, count)
140
+ c.add_tags tags
141
+ self.stats.add_group(name)
142
+ self.stats.sample(name, count, c.tags)
143
+ c
144
+ end
145
+
127
146
  def add_mark(name)
128
147
  mark = Benelux::Mark.now(name)
129
- mark.add_tags Benelux.thread_timeline.default_tags
130
148
  mark.add_tags self.default_tags
131
- Benelux.thread_timeline << mark
132
149
  self << mark
133
150
  mark
134
151
  end
135
152
 
136
153
  def add_range(name, from, to)
137
154
  range = Benelux::Range.new(name, from, to)
138
- range.add_tags Benelux.thread_timeline.default_tags
139
155
  range.add_tags self.default_tags
140
- @stats.add_keeper(name)
141
- @stats.send(name).sample(range.duration, range.tags)
142
- @ranges << range
143
- Benelux.thread_timeline.ranges << range
144
- Benelux.thread_timeline.stats.add_keeper(name)
145
- Benelux.thread_timeline.stats.send(name).sample(range.duration, range.tags)
156
+ range.add_tags from.tags
157
+ range.add_tags to.tags
158
+ self.ranges << range
159
+ self.stats.add_group(name)
160
+ self.stats.sample(name, range.duration, range.tags)
146
161
  range
147
162
  end
148
163
 
149
- def to_line
150
- marks = self.sort
151
- end
152
-
153
- def to_line2
154
- marks = self.sort
155
- str, prev = [], marks.first
156
- marks.each do |mark|
157
- str << "%s(%s):%.4f" % [mark.name, mark.thread_id, mark.to_s(prev)]
158
- prev = mark
164
+ def merge!(*timelines)
165
+ timelines.each do |tl|
166
+ self.push *tl
167
+ self.ranges.push *tl.ranges
168
+ self.stats += tl.stats
159
169
  end
160
- str.join('; ')
170
+ self
161
171
  end
172
+
162
173
  def +(other)
163
- self << other
164
- self.ranges += other.ranges
174
+ self.push *other
175
+ self.ranges.push *other.ranges
165
176
  self.stats += other.stats
166
- self.flatten!
167
177
  self
168
178
  end
169
179
  # Needs to compare thread id and call id.
@@ -0,0 +1,20 @@
1
+
2
+
3
+ module Benelux
4
+ class Track
5
+ attr_reader :name
6
+ attr_reader :thread_group
7
+ attr_reader :timeline
8
+ def initialize(n,g=nil)
9
+ @name, @thgrp = n, (g || ThreadGroup.new)
10
+ @timeline = Benelux::Timeline.new
11
+ end
12
+ def add_thread(t=Thread.current)
13
+ @thgrp.add t
14
+ t
15
+ end
16
+ def threads
17
+ @thgrp.list
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,72 @@
1
+
2
+ # = Selectable
3
+ #
4
+ # <strong>Note: Classes that include Selectable must also
5
+ # subclass Array</strong>
6
+ #
7
+ # class Something < Array
8
+ # include Selectable
9
+ # end
10
+ #
11
+ module Selectable
12
+
13
+ class SelectableError < RuntimeError; end
14
+ class TagsNotInitialized < SelectableError; end
15
+
16
+ require 'selectable/tags'
17
+ require 'selectable/object'
18
+
19
+ # Returns a Hash or Array
20
+ def Selectable.normalize(*tags)
21
+ tags.flatten!
22
+ tags = tags.first if tags.first.kind_of?(Hash) || tags.first.kind_of?(Array)
23
+ if tags.is_a?(Hash)
24
+ tags = Hash[tags.collect { |n,v| [n, v.to_s] }]
25
+ else
26
+ tags.collect! { |v| v.to_s }
27
+ end
28
+ tags
29
+ end
30
+
31
+ # Return the objects that match the given tags.
32
+ # This process is optimized for speed so there
33
+ # as few conditions as possible. One result of
34
+ # that decision is that it does not gracefully
35
+ # handle error conditions. For example, if the
36
+ # tags in an object have not been initialized,
37
+ # you will see this error:
38
+ #
39
+ # undefined method `>=' for nil:NilClass
40
+ #
41
+ def filter(*tags)
42
+ tags = Selectable.normalize tags
43
+ # select returns an Array. We want a Selectable.
44
+ items = self.select { |obj| obj.tags >= tags }
45
+ self.class.new items
46
+ end
47
+
48
+
49
+ def filter!(*tags)
50
+ tags = Selectable.normalize tags
51
+ self.delete_if { |obj| obj.tags < tags }
52
+ end
53
+
54
+ def tags
55
+ t = Selectable::Tags.new
56
+ self.each { |o| t.merge o.tags }
57
+ t
58
+ end
59
+
60
+ # Creates an alias for +filter+ called +[]+, but
61
+ # only if [] doesn't already exist in +obj+.
62
+ def self.included(obj)
63
+ alias_method :[], :filter unless obj.method_defined? :[]
64
+ end
65
+ end
66
+
67
+ class SelectableArray < Array
68
+ include Selectable
69
+ end
70
+ class SelectableHash < Hash
71
+ include Selectable
72
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # module Selectable
3
+ #
4
+ # class Global
5
+ # attr_reader :names
6
+ # def initialize(*names)
7
+ # @names = []
8
+ # add_groups names
9
+ # end
10
+ # class << self
11
+ # def group_class
12
+ # @group_class || Group
13
+ # end
14
+ # attr_writer :group_class
15
+ # end
16
+ # def group(name)
17
+ # self.send name
18
+ # end
19
+ # # Each group
20
+ # def each(&blk)
21
+ # @names.each { |name| blk.call(group(name)) }
22
+ # end
23
+ # # Each group name, group
24
+ # def each_pair(&blk)
25
+ # @names.each { |name| blk.call(name, group(name)) }
26
+ # end
27
+ # def add_groups(*args)
28
+ # args.flatten.each do |meth|
29
+ # next if has_group? meth
30
+ # @names << meth
31
+ # self.class.send :attr_reader, meth
32
+ # (g = Group.new).name = meth
33
+ # instance_variable_set("@#{meth}", g)
34
+ # end
35
+ # end
36
+ # alias_method :add_group, :add_groups
37
+ # def has_group?(name)
38
+ # @names.member? name
39
+ # end
40
+ # def +(other)
41
+ # if !other.is_a?(Benelux::Stats)
42
+ # raise TypeError, "can't convert #{other.class} into Stats"
43
+ # end
44
+ # other.names.each do |name|
45
+ # add_group name
46
+ # a = self.send(name)
47
+ # a += other.send(name)
48
+ # a
49
+ # end
50
+ # self
51
+ # end
52
+ #
53
+ #
54
+ # class Group < Array
55
+ # include Selectable
56
+ # attr_accessor :name
57
+ # def self.extend(klass)
58
+ # p 111111111111111
59
+ # end
60
+ # end
61
+ #
62
+ # end
63
+ # end
@@ -0,0 +1,42 @@
1
+
2
+ module Selectable
3
+
4
+ # Helper methods for objects with a @tags instance var
5
+ #
6
+ # e.g.
7
+ #
8
+ # class Something
9
+ # include Selectable::Object
10
+ # end
11
+ #
12
+ module Object
13
+ attr_accessor :tags
14
+ def add_tags(tags)
15
+ init_tags!
16
+ @tags.merge! Selectable.normalize tags
17
+ end
18
+ alias_method :add_tag, :add_tags
19
+ def add_tags_quick(tags)
20
+ @tags.merge! tags
21
+ end
22
+ alias_method :add_tag_quick, :add_tags_quick
23
+ def remove_tags(*tags)
24
+ raise TagsNotInitialized if @tags.nil?
25
+ tags.flatten!
26
+ @tags.delete_if { |n,v| tags.member?(n) }
27
+ end
28
+ alias_method :remove_tag, :remove_tags
29
+ def tag_values(*tags)
30
+ raise TagsNotInitialized if @tags.nil?
31
+ tags.flatten!
32
+ ret = @tags.collect { |n,v|
33
+ v if tags.empty? || tags.member?(n)
34
+ }.compact
35
+ ret
36
+ end
37
+ def init_tags!
38
+ @tags ||= Selectable::Tags.new
39
+ end
40
+ end
41
+
42
+ end
@@ -1,47 +1,10 @@
1
1
 
2
2
 
3
- module Benelux
4
-
5
- # Helper methods for objects with a @tags instance var
6
- #
7
- # e.g.
8
- #
9
- # class Something
10
- # include Benelux::TagHelpers
11
- # end
12
- #
13
- module TagHelpers
14
- attr_accessor :tags
15
- def add_tags(tags)
16
- @tags ||= Benelux::Tags.new
17
- @tags.merge! tags
18
- end
19
- alias_method :add_tag, :add_tags
20
- def remove_tags(*tags)
21
- tags.flatten!
22
- @tags ||= Benelux::Tags.new
23
- @tags.delete_if { |n,v| tags.member?(n) }
24
- end
25
- alias_method :remove_tag, :remove_tags
26
- def tag_values(*tags)
27
- tags.flatten!
28
- @tags ||= Benelux::Tags.new
29
- ret = @tags.collect { |n,v|
30
- p [:n, v]
31
- v if tags.empty? || tags.member?(n)
32
- }.compact
33
- ret
34
- end
35
- def self.normalize(tags={})
36
- tags = tags.first if tags.kind_of?(Array) && tags.first.kind_of?(Hash)
37
- tags = [tags].flatten unless tags.kind_of?(Hash)
38
- tags
39
- end
40
- end
3
+ module Selectable
41
4
 
42
5
  # An example of filtering an Array of tagged objects based
43
6
  # on a provided Hash of tags or Array of tag values. +obj+
44
- # in this case would be an object that includes TagHelpers.
7
+ # in this case would be an object that includes Taggable.
45
8
  #
46
9
  # class Something
47
10
  # def [](tags={})
@@ -67,9 +30,8 @@ module Benelux
67
30
  end
68
31
 
69
32
  def ==(other)
70
- # other = Benelux::TagHelpers.normalize other
71
33
  if other.is_a?(Array)
72
- (self.values & other).sort == other.sort
34
+ self.values.sort == other.sort
73
35
  else
74
36
  super(other)
75
37
  end
@@ -87,13 +49,12 @@ module Benelux
87
49
  # a > [2, 1] # => false
88
50
  #
89
51
  def <=>(b)
90
- #other = Benelux::TagHelpers.normalize other
91
52
  return 0 if self == b
92
53
  self.send :"compare_#{b.class}", b
93
54
  end
94
55
 
95
- def >(other) (self <=> other) > 0 end
96
- def <(other) (self <=> other) < 0 end
56
+ def >(other) (self <=> other) > 0 end
57
+ def <(other) (self <=> other) < 0 end
97
58
 
98
59
  def <=(other) (self <=> other) <= 0 end
99
60
  def >=(other) (self <=> other) >= 0 end
@@ -105,12 +66,25 @@ module Benelux
105
66
  return -1 unless (a.values_at(*b.keys) & b.values).size >= b.size
106
67
  1
107
68
  end
108
- alias_method :"compare_Benelux::Tags", :compare_Hash
69
+ alias_method :"compare_Selectable::Tags", :compare_Hash
109
70
 
110
71
  def compare_Array(b)
111
72
  return -1 unless (self.values & b).size >= b.size
112
73
  1
113
74
  end
75
+
76
+ def method_missing(meth, *args)
77
+ raise SelectableError, "#{meth}: #{args.first} is not a Hash or Array"
78
+ end
79
+
80
+ ## NOTE: This is helpful but defensive. Ponder!
81
+ ##def compare_forced_array(b)
82
+ ## compare_Array([b])
83
+ ##end
84
+ ##alias_method :compare_String, :compare_forced_array
85
+ ##alias_method :compare_Symbol, :compare_forced_array
86
+ ##alias_method :compare_Fixnum, :compare_forced_array
114
87
 
115
88
  end
89
+
116
90
  end
@@ -3,13 +3,30 @@ group "Benelux"
3
3
 
4
4
  library :benelux, 'lib'
5
5
  tryouts "Calculator" do
6
-
6
+ set :base, Benelux::Stats::Calculator.new
7
7
  dream :class, Benelux::Stats::Calculator
8
8
  dream :n, 10
9
+ dream :sum, 45
10
+ dream :sumsq, 285
11
+ dream :min, 0
12
+ dream :max, 9
13
+ dream :proc, lambda { |calc| calc.sd.to_i == 3 }
9
14
  drill "can keep stats" do
10
- keeper = Benelux::Stats::Calculator.new
11
- 10.times { keeper.sample(rand) }
12
- keeper
15
+ 10.times { |i| base.sample(i) }
16
+ base
17
+ end
18
+
19
+ dream true
20
+ drill "can add stats" do
21
+ by_sample = Benelux::Stats::Calculator.new
22
+ 10.times { |i| by_sample.sample(i) }
23
+ by_sample += base
24
+ by_merge = Benelux::Stats::Calculator.new
25
+ by_merge.merge! base
26
+ by_merge.merge! base
27
+ stash :sample, by_sample
28
+ stash :merge, by_merge
29
+ by_sample == by_merge
13
30
  end
14
31
 
15
32
  end