ffwd 0.1.0
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.
- checksums.yaml +7 -0
- data/bin/ffwd +9 -0
- data/bin/fwc +15 -0
- data/lib/em/all.rb +68 -0
- data/lib/ffwd.rb +250 -0
- data/lib/ffwd/channel.rb +62 -0
- data/lib/ffwd/circular_buffer.rb +78 -0
- data/lib/ffwd/connection.rb +40 -0
- data/lib/ffwd/core.rb +173 -0
- data/lib/ffwd/core/emitter.rb +38 -0
- data/lib/ffwd/core/interface.rb +47 -0
- data/lib/ffwd/core/processor.rb +92 -0
- data/lib/ffwd/core/reporter.rb +32 -0
- data/lib/ffwd/debug.rb +76 -0
- data/lib/ffwd/debug/connection.rb +48 -0
- data/lib/ffwd/debug/monitor_session.rb +71 -0
- data/lib/ffwd/debug/tcp.rb +82 -0
- data/lib/ffwd/event.rb +65 -0
- data/lib/ffwd/event_emitter.rb +57 -0
- data/lib/ffwd/handler.rb +43 -0
- data/lib/ffwd/lifecycle.rb +92 -0
- data/lib/ffwd/logging.rb +139 -0
- data/lib/ffwd/metric.rb +55 -0
- data/lib/ffwd/metric_emitter.rb +50 -0
- data/lib/ffwd/plugin.rb +149 -0
- data/lib/ffwd/plugin/json_line.rb +47 -0
- data/lib/ffwd/plugin/json_line/connection.rb +118 -0
- data/lib/ffwd/plugin/log.rb +35 -0
- data/lib/ffwd/plugin/log/writer.rb +42 -0
- data/lib/ffwd/plugin_channel.rb +64 -0
- data/lib/ffwd/plugin_loader.rb +121 -0
- data/lib/ffwd/processor.rb +96 -0
- data/lib/ffwd/processor/count.rb +109 -0
- data/lib/ffwd/processor/histogram.rb +200 -0
- data/lib/ffwd/processor/rate.rb +116 -0
- data/lib/ffwd/producing_client.rb +181 -0
- data/lib/ffwd/protocol.rb +28 -0
- data/lib/ffwd/protocol/tcp.rb +126 -0
- data/lib/ffwd/protocol/tcp/bind.rb +64 -0
- data/lib/ffwd/protocol/tcp/connection.rb +107 -0
- data/lib/ffwd/protocol/tcp/flushing_connect.rb +135 -0
- data/lib/ffwd/protocol/tcp/plain_connect.rb +74 -0
- data/lib/ffwd/protocol/udp.rb +48 -0
- data/lib/ffwd/protocol/udp/bind.rb +64 -0
- data/lib/ffwd/protocol/udp/connect.rb +110 -0
- data/lib/ffwd/reporter.rb +65 -0
- data/lib/ffwd/retrier.rb +72 -0
- data/lib/ffwd/schema.rb +92 -0
- data/lib/ffwd/schema/default.rb +36 -0
- data/lib/ffwd/schema/spotify100.rb +58 -0
- data/lib/ffwd/statistics.rb +29 -0
- data/lib/ffwd/statistics/collector.rb +99 -0
- data/lib/ffwd/statistics/system_statistics.rb +255 -0
- data/lib/ffwd/tunnel.rb +27 -0
- data/lib/ffwd/tunnel/plugin.rb +47 -0
- data/lib/ffwd/tunnel/tcp.rb +60 -0
- data/lib/ffwd/tunnel/udp.rb +61 -0
- data/lib/ffwd/utils.rb +46 -0
- data/lib/ffwd/version.rb +18 -0
- data/lib/fwc.rb +206 -0
- metadata +163 -0
@@ -0,0 +1,200 @@
|
|
1
|
+
# $LICENSE
|
2
|
+
# Copyright 2013-2014 Spotify AB. All rights reserved.
|
3
|
+
#
|
4
|
+
# The contents of this file are licensed under the Apache License, Version 2.0
|
5
|
+
# (the "License"); you may not use this file except in compliance with the
|
6
|
+
# License. You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
13
|
+
# License for the specific language governing permissions and limitations under
|
14
|
+
# the License.
|
15
|
+
|
16
|
+
require 'ffwd/event'
|
17
|
+
require 'ffwd/logging'
|
18
|
+
require 'ffwd/processor'
|
19
|
+
require 'ffwd/reporter'
|
20
|
+
require 'ffwd/utils'
|
21
|
+
|
22
|
+
module FFWD::Processor
|
23
|
+
#
|
24
|
+
# Implements histogram statistics over a tumbling time window.
|
25
|
+
#
|
26
|
+
# Histogram received metrics continiuosly and regularly flushes out the
|
27
|
+
# following statistics.
|
28
|
+
#
|
29
|
+
# <key>.min - Min value collected.
|
30
|
+
# <key>.max - Max value collected.
|
31
|
+
# <key>.mean - Mean value collected.
|
32
|
+
# <key>.p50 - The 50th percentile value collected.
|
33
|
+
# <key>.p75 - The 75th percentile value collected.
|
34
|
+
# <key>.p95 - The 95th percentile value collected.
|
35
|
+
# <key>.p99 - The 99th percentile value collected.
|
36
|
+
# <key>.p999 - The 99.9th percentile value collected.
|
37
|
+
#
|
38
|
+
class HistogramProcessor
|
39
|
+
include FFWD::Processor
|
40
|
+
include FFWD::Logging
|
41
|
+
include FFWD::Reporter
|
42
|
+
|
43
|
+
register_processor "histogram"
|
44
|
+
setup_reporter(
|
45
|
+
:reporter_meta => {:processor => "histogram"},
|
46
|
+
:keys => [:dropped, :bucket_dropped, :received]
|
47
|
+
)
|
48
|
+
|
49
|
+
DEFAULT_MISSING = 0
|
50
|
+
|
51
|
+
DEFAULT_PERCENTILES = {
|
52
|
+
:p50 => {:percentage => 0.50, :info => "50th"},
|
53
|
+
:p75 => {:percentage => 0.75, :info => "75th"},
|
54
|
+
:p95 => {:percentage => 0.95, :info => "95th"},
|
55
|
+
:p99 => {:percentage => 0.99, :info => "99th"},
|
56
|
+
:p999 => {:percentage => 0.999, :info => "99.9th"},
|
57
|
+
}
|
58
|
+
|
59
|
+
#
|
60
|
+
# Options:
|
61
|
+
#
|
62
|
+
# :window - Define at what period the cache is flushed and generates
|
63
|
+
# metrics.
|
64
|
+
# :cache_limit - Limit the amount of cache entries (by key).
|
65
|
+
# :bucket_limit - Limit the amount of limits for each cache entry.
|
66
|
+
# :precision - Precision of emitted metrics.
|
67
|
+
# :percentiles - Configuration hash of percentile metrics.
|
68
|
+
# Structure:
|
69
|
+
# {:p10 => {:info => "Some description", :percentage => 0.1}, ...}
|
70
|
+
def initialize emitter, opts={}
|
71
|
+
@emitter = emitter
|
72
|
+
|
73
|
+
@window = opts[:window] || 10
|
74
|
+
@cache_limit = opts[:cache_limit] || 1000
|
75
|
+
@bucket_limit = opts[:bucket_limit] || 10000
|
76
|
+
@precision = opts[:precision] || 3
|
77
|
+
@missing = opts[:missing] || DEFAULT_MISSING
|
78
|
+
@percentiles = opts[:percentiles] || DEFAULT_PERCENTILES
|
79
|
+
|
80
|
+
# Dropped values that would have gone into a bucket.
|
81
|
+
@cache = {}
|
82
|
+
|
83
|
+
starting do
|
84
|
+
log.info "Starting histogram processor on a window of #{@window}s"
|
85
|
+
end
|
86
|
+
|
87
|
+
stopping do
|
88
|
+
log.info "Stopping histogram processor"
|
89
|
+
@timer.cancel if @timer
|
90
|
+
@timer = nil
|
91
|
+
digest!
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def check_timer
|
96
|
+
return if @timer
|
97
|
+
|
98
|
+
log.debug "Starting timer"
|
99
|
+
|
100
|
+
@timer = EM::Timer.new(@window) do
|
101
|
+
@timer = nil
|
102
|
+
digest!
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Digest the cache.
|
107
|
+
def digest!
|
108
|
+
if @cache.empty?
|
109
|
+
return
|
110
|
+
end
|
111
|
+
|
112
|
+
ms = FFWD.timing do
|
113
|
+
@cache.each do |key, bucket|
|
114
|
+
calculate(bucket) do |p, info, value|
|
115
|
+
@emitter.metric.emit(
|
116
|
+
:key => "#{key}.#{p}", :source => key,
|
117
|
+
:value => value, :description => "#{info} of #{key}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
@cache = {}
|
122
|
+
end
|
123
|
+
|
124
|
+
log.debug "Digest took #{ms}ms"
|
125
|
+
end
|
126
|
+
|
127
|
+
def calculate bucket
|
128
|
+
total = bucket.size
|
129
|
+
|
130
|
+
map = {}
|
131
|
+
|
132
|
+
@percentiles.each do |k, v|
|
133
|
+
index = (total * v[:percentage]).ceil - 1
|
134
|
+
|
135
|
+
if (c = map[index]).nil?
|
136
|
+
info = "#{v[:info]} percentile"
|
137
|
+
c = map[index] = {:info => info, :values => []}
|
138
|
+
end
|
139
|
+
|
140
|
+
c[:values] << {:name => k, :value => nil}
|
141
|
+
end
|
142
|
+
|
143
|
+
max = nil
|
144
|
+
min = nil
|
145
|
+
sum = 0.0
|
146
|
+
mean = nil
|
147
|
+
|
148
|
+
bucket.sort.each_with_index do |t, index|
|
149
|
+
max = t if max.nil? or t > max
|
150
|
+
min = t if min.nil? or t < min
|
151
|
+
sum += t
|
152
|
+
|
153
|
+
unless (c = map[index]).nil?
|
154
|
+
c[:values].each{|d| d[:value] = t}
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
mean = sum / total
|
159
|
+
|
160
|
+
unless @precision.nil?
|
161
|
+
max = max.round(@precision)
|
162
|
+
min = min.round(@precision)
|
163
|
+
sum = sum.round(@precision)
|
164
|
+
mean = mean.round(@precision)
|
165
|
+
|
166
|
+
map.each do |index, c|
|
167
|
+
c[:values].each{|d| d[:value] = d[:value].round(@precision)}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
yield "max", "Max", max
|
172
|
+
yield "min", "Min", min
|
173
|
+
yield "sum", "Sum", sum
|
174
|
+
yield "mean", "Mean", mean
|
175
|
+
|
176
|
+
map.each do |index, c|
|
177
|
+
c[:values].each do |d|
|
178
|
+
yield d[:name], c[:info], d[:value]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def process m
|
184
|
+
key = m[:key]
|
185
|
+
value = m[:value] || @missing
|
186
|
+
|
187
|
+
if (bucket = @cache[key]).nil?
|
188
|
+
return increment :dropped if @cache.size >= @cache_limit
|
189
|
+
@cache[key] = bucket = []
|
190
|
+
end
|
191
|
+
|
192
|
+
return increment :bucket_dropped if bucket.size >= @bucket_limit
|
193
|
+
return increment :dropped if stopped?
|
194
|
+
increment :received
|
195
|
+
|
196
|
+
bucket << value
|
197
|
+
check_timer
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# $LICENSE
|
2
|
+
# Copyright 2013-2014 Spotify AB. All rights reserved.
|
3
|
+
#
|
4
|
+
# The contents of this file are licensed under the Apache License, Version 2.0
|
5
|
+
# (the "License"); you may not use this file except in compliance with the
|
6
|
+
# License. You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
13
|
+
# License for the specific language governing permissions and limitations under
|
14
|
+
# the License.
|
15
|
+
|
16
|
+
require 'ffwd/processor'
|
17
|
+
require 'ffwd/logging'
|
18
|
+
require 'ffwd/reporter'
|
19
|
+
|
20
|
+
module FFWD::Processor
|
21
|
+
#
|
22
|
+
# Implements rate statistics (similar to derive in collectd).
|
23
|
+
#
|
24
|
+
class RateProcessor
|
25
|
+
include FFWD::Logging
|
26
|
+
include FFWD::Processor
|
27
|
+
include FFWD::Reporter
|
28
|
+
|
29
|
+
register_processor "rate"
|
30
|
+
setup_reporter(
|
31
|
+
:reporter_meta => {:processor => "rate"},
|
32
|
+
:keys => [:dropped, :expired, :received]
|
33
|
+
)
|
34
|
+
|
35
|
+
# Options:
|
36
|
+
#
|
37
|
+
# :precision - The precision to round to for emitted values.
|
38
|
+
# :cache_limit - Maxiumum amount of items allowed in the cache.
|
39
|
+
# :min_age - Minimum age that an item has to have in the cache to calculate
|
40
|
+
# rates.
|
41
|
+
# This exists to prevent too frequent updates to the cache which would
|
42
|
+
# yield very static or jumpy rates.
|
43
|
+
# Can be set to null to disable.
|
44
|
+
# :ttl - Allowed age of items in cache in seconds.
|
45
|
+
# If this is nil, items will never expire, so old elements will not be
|
46
|
+
# expunged until data type is restarted.
|
47
|
+
def initialize emitter, opts={}
|
48
|
+
@emitter = emitter
|
49
|
+
|
50
|
+
@precision = opts[:precision] || 3
|
51
|
+
@limit = opts[:cache_limit] || 10000
|
52
|
+
@min_age = opts[:min_age] || 0.5
|
53
|
+
@ttl = opts[:ttl] || 600
|
54
|
+
# keep a reference to the expire cache to prevent having to allocate it
|
55
|
+
# all the time.
|
56
|
+
@expire = Hash.new
|
57
|
+
# Cache of active events.
|
58
|
+
@cache = Hash.new
|
59
|
+
|
60
|
+
starting do
|
61
|
+
log.info "Starting rate processor (ttl: #{@ttl})"
|
62
|
+
@timer = EM.add_periodic_timer(@ttl){expire!} unless @ttl.nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
stopping do
|
66
|
+
log.info "Stopping rate processor"
|
67
|
+
@timer.cancel if @timer
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Expire cached events that are too old.
|
72
|
+
def expire!
|
73
|
+
now = Time.new
|
74
|
+
|
75
|
+
@cache.each do |key, value|
|
76
|
+
diff = (now - value[:time])
|
77
|
+
next if diff < @ttl
|
78
|
+
@expire[key] = value
|
79
|
+
end
|
80
|
+
|
81
|
+
unless @expire.empty?
|
82
|
+
increment :expired, @cache.size - @expire.size
|
83
|
+
@cache = @expire
|
84
|
+
@expire = Hash.new
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def process msg
|
89
|
+
key = msg[:key]
|
90
|
+
time = msg[:time]
|
91
|
+
value = msg[:value] || 0
|
92
|
+
|
93
|
+
unless (prev = @cache[key]).nil?
|
94
|
+
prev_time = prev[:time]
|
95
|
+
prev_value = prev[:value]
|
96
|
+
|
97
|
+
diff = (time - prev_time)
|
98
|
+
|
99
|
+
valid = @ttl.nil? or diff < @ttl
|
100
|
+
aged = @min_age.nil? or diff > @min_age
|
101
|
+
|
102
|
+
if diff > 0 and valid and aged
|
103
|
+
rate = ((value - prev_value) / diff)
|
104
|
+
rate = rate.round(@precision) unless @precision.nil?
|
105
|
+
@emitter.metric.emit(
|
106
|
+
:key => "#{key}.rate", :source => key, :value => rate)
|
107
|
+
end
|
108
|
+
else
|
109
|
+
return increment :dropped if @cache.size >= @limit
|
110
|
+
end
|
111
|
+
|
112
|
+
increment :received
|
113
|
+
@cache[key] = {:key => key, :time => time, :value => value}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# $LICENSE
|
2
|
+
# Copyright 2013-2014 Spotify AB. All rights reserved.
|
3
|
+
#
|
4
|
+
# The contents of this file are licensed under the Apache License, Version 2.0
|
5
|
+
# (the "License"); you may not use this file except in compliance with the
|
6
|
+
# License. You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
12
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
13
|
+
# License for the specific language governing permissions and limitations under
|
14
|
+
# the License.
|
15
|
+
|
16
|
+
require_relative 'lifecycle'
|
17
|
+
require_relative 'reporter'
|
18
|
+
require_relative 'logging'
|
19
|
+
|
20
|
+
module FFWD
|
21
|
+
# A client implementation that delegates all work to other threads.
|
22
|
+
class ProducingClient
|
23
|
+
include FFWD::Reporter
|
24
|
+
include FFWD::Logging
|
25
|
+
|
26
|
+
class Producer
|
27
|
+
def setup; raise "not implemented: setup"; end
|
28
|
+
def teardown; raise "not implemented: teardown"; end
|
29
|
+
def produce events, metrics; raise "not implemented: produce"; end
|
30
|
+
end
|
31
|
+
|
32
|
+
setup_reporter :keys => [
|
33
|
+
# number of events/metrics that we attempted to dispatch but failed.
|
34
|
+
:failed_events, :failed_metrics,
|
35
|
+
# number of events/metrics that were dropped because the output buffers
|
36
|
+
# are full.
|
37
|
+
:dropped_events, :dropped_metrics,
|
38
|
+
# number of events/metrics successfully sent.
|
39
|
+
:sent_events, :sent_metrics,
|
40
|
+
# number of requests that take longer than the allowed period.
|
41
|
+
:slow_requests
|
42
|
+
]
|
43
|
+
|
44
|
+
def reporter_meta
|
45
|
+
@reporter_meta ||= @producer.reporter_meta.merge(
|
46
|
+
:type => "producing_client_out")
|
47
|
+
end
|
48
|
+
|
49
|
+
def report!
|
50
|
+
super do |m|
|
51
|
+
yield m
|
52
|
+
end
|
53
|
+
|
54
|
+
return unless @producer_is_reporter
|
55
|
+
|
56
|
+
@producer.report! do |m|
|
57
|
+
yield m
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialize channel, producer, flush_period, event_limit, metric_limit
|
62
|
+
@flush_period = flush_period
|
63
|
+
@event_limit = event_limit
|
64
|
+
@metric_limit = metric_limit
|
65
|
+
|
66
|
+
if @flush_period <= 0
|
67
|
+
raise "Invalid flush period: #{flush_period}"
|
68
|
+
end
|
69
|
+
|
70
|
+
@producer = producer
|
71
|
+
@producer_is_reporter = FFWD.is_reporter? producer
|
72
|
+
|
73
|
+
@events = []
|
74
|
+
@metrics = []
|
75
|
+
|
76
|
+
# Pending request.
|
77
|
+
@request = nil
|
78
|
+
@timer = nil
|
79
|
+
|
80
|
+
@subs = []
|
81
|
+
|
82
|
+
channel.starting do
|
83
|
+
@timer = EM::PeriodicTimer.new(@flush_period){safer_flush!}
|
84
|
+
|
85
|
+
@subs << channel.event_subscribe do |e|
|
86
|
+
if @events.size >= @event_limit
|
87
|
+
increment :dropped_events
|
88
|
+
next
|
89
|
+
end
|
90
|
+
|
91
|
+
@events << e
|
92
|
+
end
|
93
|
+
|
94
|
+
@subs << channel.metric_subscribe do |m|
|
95
|
+
if @metrics.size >= @metric_limit
|
96
|
+
increment :dropped_metrics
|
97
|
+
next
|
98
|
+
end
|
99
|
+
|
100
|
+
@metrics << m
|
101
|
+
end
|
102
|
+
|
103
|
+
@producer.setup
|
104
|
+
end
|
105
|
+
|
106
|
+
channel.stopping do
|
107
|
+
if @timer
|
108
|
+
@timer.cancel
|
109
|
+
@timer = nil
|
110
|
+
end
|
111
|
+
|
112
|
+
flush!
|
113
|
+
|
114
|
+
@subs.each(&:unsubscribe).clear
|
115
|
+
|
116
|
+
@metrics.clear
|
117
|
+
@events.clear
|
118
|
+
|
119
|
+
@producer.teardown
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Apply some heuristics to determine if we can 'ignore' the current flush
|
124
|
+
# to prevent loss of data.
|
125
|
+
#
|
126
|
+
# Checks that if a request is pending; we have not breached the limit of
|
127
|
+
# allowed events.
|
128
|
+
def safer_flush!
|
129
|
+
if @request
|
130
|
+
increment :slow_requests
|
131
|
+
|
132
|
+
ignore_flush = (
|
133
|
+
@events.size < @event_limit or
|
134
|
+
@metrics.size < @metric_limit)
|
135
|
+
|
136
|
+
return if ignore_flush
|
137
|
+
end
|
138
|
+
|
139
|
+
flush!
|
140
|
+
end
|
141
|
+
|
142
|
+
def flush!
|
143
|
+
if @request or not @request = @producer.produce(@events, @metrics)
|
144
|
+
increment :dropped_events, @events.size
|
145
|
+
increment :dropped_metrics, @metrics.size
|
146
|
+
return
|
147
|
+
end
|
148
|
+
|
149
|
+
@request.callback do
|
150
|
+
increment :sent_events, @events.size
|
151
|
+
increment :sent_metrics, @metrics.size
|
152
|
+
@request = nil
|
153
|
+
end
|
154
|
+
|
155
|
+
@request.errback do
|
156
|
+
increment :failed_events, @events.size
|
157
|
+
increment :failed_metrics, @metrics.size
|
158
|
+
@request = nil
|
159
|
+
end
|
160
|
+
rescue => e
|
161
|
+
increment :failed_events, @events.size
|
162
|
+
increment :failed_metrics, @metrics.size
|
163
|
+
log.error "Failed to produce", e
|
164
|
+
ensure
|
165
|
+
@events.clear
|
166
|
+
@metrics.clear
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
DEFAULT_FLUSH_PERIOD = 10
|
171
|
+
DEFAULT_EVENT_LIMIT = 10000
|
172
|
+
DEFAULT_METRIC_LIMIT = 10000
|
173
|
+
DEFAULT_FLUSH_SIZE = 1000
|
174
|
+
|
175
|
+
def self.producing_client channel, producer, opts
|
176
|
+
flush_period = opts[:flush_period] || DEFAULT_FLUSH_PERIOD
|
177
|
+
event_limit = opts[:event_limit] || DEFAULT_EVENT_LIMIT
|
178
|
+
metric_limit = opts[:metric_limit] || DEFAULT_METRIC_LIMIT
|
179
|
+
ProducingClient.new channel, producer, flush_period, event_limit, metric_limit
|
180
|
+
end
|
181
|
+
end
|