ffwd 0.1.7 → 0.2.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/lib/ffwd.rb +34 -10
- data/lib/ffwd/core.rb +13 -11
- data/lib/ffwd/core/emitter.rb +0 -2
- data/lib/ffwd/core/interface.rb +5 -2
- data/lib/ffwd/core/processor.rb +4 -5
- data/lib/ffwd/debug/monitor_session.rb +3 -6
- data/lib/ffwd/debug/tcp.rb +17 -12
- data/lib/ffwd/handler.rb +1 -1
- data/lib/ffwd/plugin.rb +20 -15
- data/lib/ffwd/plugin/json.rb +12 -20
- data/lib/ffwd/plugin/json/connection.rb +4 -2
- data/lib/ffwd/plugin/log.rb +17 -2
- data/lib/ffwd/plugin/log/writer.rb +4 -0
- data/lib/ffwd/plugin_channel.rb +8 -8
- data/lib/ffwd/processor.rb +11 -4
- data/lib/ffwd/processor/count.rb +16 -6
- data/lib/ffwd/processor/histogram.rb +26 -15
- data/lib/ffwd/processor/rate.rb +16 -6
- data/lib/ffwd/protocol/tcp.rb +47 -88
- data/lib/ffwd/protocol/tcp/bind.rb +22 -10
- data/lib/ffwd/protocol/tcp/connection.rb +23 -6
- data/lib/ffwd/protocol/tcp/flushing_connect.rb +42 -25
- data/lib/ffwd/protocol/tcp/plain_connect.rb +15 -3
- data/lib/ffwd/protocol/udp.rb +42 -17
- data/lib/ffwd/protocol/udp/bind.rb +21 -10
- data/lib/ffwd/protocol/udp/connect.rb +22 -9
- data/lib/ffwd/retrier.rb +4 -1
- data/lib/ffwd/schema.rb +10 -3
- data/lib/ffwd/statistics/collector.rb +31 -23
- data/lib/ffwd/test/protocol.rb +42 -0
- data/lib/ffwd/tunnel/tcp.rb +3 -1
- data/lib/ffwd/utils.rb +7 -0
- data/lib/ffwd/version.rb +1 -1
- metadata +56 -68
- data/lib/ffwd/circular_buffer.rb +0 -78
- data/lib/ffwd/statistics.rb +0 -29
- data/lib/ffwd/tunnel.rb +0 -27
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4b630458a10baaf2b380c2fea5d264c0b5899dfb
|
4
|
+
data.tar.gz: de1dbbce8ec3bbd5a4d8acd85dc2b7f6c5ef9cfa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d32fad236f6af767352403f042f9cf03a5e7133a41081a0d390715467339ed579e0993b853a433dbbc5cae02c433ad44b4bcadea58228e2c68a9983e6f88219
|
7
|
+
data.tar.gz: b60bf9c734110e417fd45c9bb8282e9224780146bb2bd403b62d5a315c2ff26d061b8eaa303a266a1fd61f2ecc2dfcdc19ae99b1cf9562b8b222000191e509a0
|
data/lib/ffwd.rb
CHANGED
@@ -25,9 +25,8 @@ require_relative 'ffwd/schema'
|
|
25
25
|
require_relative 'ffwd/version'
|
26
26
|
|
27
27
|
module FFWD
|
28
|
-
DEFAULT_PLUGIN_DIRECTORIES = [
|
29
|
-
|
30
|
-
]
|
28
|
+
DEFAULT_PLUGIN_DIRECTORIES = ['./plugins' ]
|
29
|
+
DEFAULT_CONFIG_PREFIXES = ['./ffwd.d']
|
31
30
|
|
32
31
|
def self.load_yaml path
|
33
32
|
return YAML.load_file path
|
@@ -70,7 +69,7 @@ module FFWD
|
|
70
69
|
c = load_yaml entry_path
|
71
70
|
|
72
71
|
if c.nil?
|
73
|
-
log.
|
72
|
+
log.warning "Ignoring: #{entry_path} (invalid yaml)"
|
74
73
|
next
|
75
74
|
end
|
76
75
|
|
@@ -82,6 +81,7 @@ module FFWD
|
|
82
81
|
@@opts ||= {:debug => false, :config => nil, :config_dir => nil,
|
83
82
|
:list_plugins => false, :list_schemas => false,
|
84
83
|
:dump_config => false, :show_version => false,
|
84
|
+
:config_prefixes => DEFAULT_CONFIG_PREFIXES,
|
85
85
|
:config_paths => [],
|
86
86
|
:plugin_directories => DEFAULT_PLUGIN_DIRECTORIES}
|
87
87
|
end
|
@@ -95,9 +95,15 @@ module FFWD
|
|
95
95
|
end
|
96
96
|
|
97
97
|
o.on "-c", "--config <path>", "Load the specified configuration file." do |path|
|
98
|
+
puts "WARNING: Deprecated option '-c #{path}'."
|
99
|
+
puts " Use positional argument to specify configuration!"
|
98
100
|
opts[:config_paths] << path
|
99
101
|
end
|
100
102
|
|
103
|
+
o.on "-D", "--config-prefix <path>", "Scan for configuration files relative to this directory." do |path|
|
104
|
+
opts[:config_prefixes] << path
|
105
|
+
end
|
106
|
+
|
101
107
|
o.on "-d", "--config-directory <path>", "Load configuration files from the specified directory." do |path|
|
102
108
|
opts[:config_dir] = path
|
103
109
|
end
|
@@ -132,13 +138,13 @@ module FFWD
|
|
132
138
|
plugins = {}
|
133
139
|
|
134
140
|
plugins[:tunnel] = FFWD::Plugin.load_plugins(
|
135
|
-
log, "Tunnel", config[:tunnel], :tunnel)
|
141
|
+
log, "Tunnel", config[:tunnel], :input, :tunnel)
|
136
142
|
|
137
143
|
plugins[:input] = FFWD::Plugin.load_plugins(
|
138
|
-
log, "Input", config[:input], :input)
|
144
|
+
log, "Input", config[:input], :input, :bind)
|
139
145
|
|
140
146
|
plugins[:output] = FFWD::Plugin.load_plugins(
|
141
|
-
log, "Output", config[:output], :output)
|
147
|
+
log, "Output", config[:output], :output, :connect)
|
142
148
|
|
143
149
|
plugins
|
144
150
|
end
|
@@ -219,8 +225,24 @@ module FFWD
|
|
219
225
|
puts " https://github.com/spotify/ffwd"
|
220
226
|
end
|
221
227
|
|
228
|
+
def self.match_any_config_path prefixes, path
|
229
|
+
return path if File.file? path
|
230
|
+
|
231
|
+
prefixes.each do |prefix|
|
232
|
+
full = File.join prefix, path
|
233
|
+
next unless File.file? full
|
234
|
+
return full
|
235
|
+
end
|
236
|
+
|
237
|
+
return nil
|
238
|
+
end
|
239
|
+
|
222
240
|
def self.main args
|
223
|
-
parse_options
|
241
|
+
positional = parse_options(args)
|
242
|
+
|
243
|
+
positional.each do |path|
|
244
|
+
opts[:config_paths] << path
|
245
|
+
end
|
224
246
|
|
225
247
|
if opts[:show_version]
|
226
248
|
puts "ffwd version: #{FFWD::VERSION}"
|
@@ -232,7 +254,9 @@ module FFWD
|
|
232
254
|
config = {}
|
233
255
|
|
234
256
|
opts[:config_paths].each do |path|
|
235
|
-
|
257
|
+
path = match_any_config_path opts[:config_prefixes], path
|
258
|
+
|
259
|
+
unless path
|
236
260
|
puts "Configuration path does not exist: #{path}"
|
237
261
|
puts ""
|
238
262
|
puts parser.help
|
@@ -240,7 +264,7 @@ module FFWD
|
|
240
264
|
end
|
241
265
|
|
242
266
|
return 0 unless source = load_yaml(path)
|
243
|
-
|
267
|
+
puts "Loaded: #{path}"
|
244
268
|
merge_configurations config, source
|
245
269
|
end
|
246
270
|
|
data/lib/ffwd/core.rb
CHANGED
@@ -23,7 +23,6 @@ require_relative 'logging'
|
|
23
23
|
require_relative 'plugin_channel'
|
24
24
|
require_relative 'processor'
|
25
25
|
require_relative 'protocol'
|
26
|
-
require_relative 'statistics'
|
27
26
|
require_relative 'utils'
|
28
27
|
|
29
28
|
require_relative 'core/emitter'
|
@@ -31,6 +30,8 @@ require_relative 'core/interface'
|
|
31
30
|
require_relative 'core/processor'
|
32
31
|
require_relative 'core/reporter'
|
33
32
|
|
33
|
+
require_relative 'statistics/collector'
|
34
|
+
|
34
35
|
module FFWD
|
35
36
|
class Core
|
36
37
|
include FFWD::Lifecycle
|
@@ -46,8 +47,8 @@ module FFWD
|
|
46
47
|
@core_opts = opts[:core] || {}
|
47
48
|
@processors = FFWD::Processor.load_processors(opts[:processor] || {})
|
48
49
|
|
49
|
-
@output_channel = FFWD::PluginChannel.build 'output'
|
50
|
-
@input_channel = FFWD::PluginChannel.build 'input'
|
50
|
+
@output_channel = FFWD::PluginChannel.build 'core.output'
|
51
|
+
@input_channel = FFWD::PluginChannel.build 'core.input'
|
51
52
|
|
52
53
|
@system_channel = Channel.new log, "system_channel"
|
53
54
|
|
@@ -66,8 +67,8 @@ module FFWD
|
|
66
67
|
|
67
68
|
if @debug_opts
|
68
69
|
@debug = FFWD::Debug.setup @debug_opts
|
69
|
-
@debug.monitor
|
70
|
-
@debug.monitor
|
70
|
+
@debug.monitor @input_channel, FFWD::Debug::Input
|
71
|
+
@debug.monitor @output_channel, FFWD::Debug::Output
|
71
72
|
@debug.depend_on self
|
72
73
|
end
|
73
74
|
|
@@ -75,7 +76,8 @@ module FFWD
|
|
75
76
|
@statistics = nil
|
76
77
|
|
77
78
|
if config = @statistics_opts
|
78
|
-
@statistics = FFWD::Statistics.
|
79
|
+
@statistics = FFWD::Statistics::Collector.build(
|
80
|
+
@emitter, @system_channel, config)
|
79
81
|
@statistics.depend_on self
|
80
82
|
end
|
81
83
|
|
@@ -86,19 +88,19 @@ module FFWD
|
|
86
88
|
|
87
89
|
@interface.depend_on self
|
88
90
|
|
89
|
-
@input_instances = @input_plugins.map do |
|
90
|
-
|
91
|
+
@input_instances = @input_plugins.map do |factory|
|
92
|
+
factory.call @interface
|
91
93
|
end
|
92
94
|
|
93
|
-
@output_instances = @output_plugins.map do |
|
94
|
-
|
95
|
+
@output_instances = @output_plugins.map do |factory|
|
96
|
+
factory.call @interface
|
95
97
|
end
|
96
98
|
|
97
99
|
unless @statistics.nil?
|
98
100
|
reporters = [@input_channel, @output_channel, @processor]
|
99
101
|
reporters += @input_instances.select{|i| FFWD.is_reporter?(i)}
|
100
102
|
reporters += @output_instances.select{|i| FFWD.is_reporter?(i)}
|
101
|
-
@statistics.register "core", Core::Reporter.new(reporters)
|
103
|
+
@statistics.register self, "core", Core::Reporter.new(reporters)
|
102
104
|
end
|
103
105
|
|
104
106
|
# Make the core-related channels depend on core.
|
data/lib/ffwd/core/emitter.rb
CHANGED
data/lib/ffwd/core/interface.rb
CHANGED
@@ -25,8 +25,11 @@ module FFWD
|
|
25
25
|
attr_reader :tunnel_plugins, :statistics, :debug, :processors
|
26
26
|
attr_reader :tags, :attributes
|
27
27
|
|
28
|
-
def initialize(
|
29
|
-
|
28
|
+
def initialize(
|
29
|
+
input, output,
|
30
|
+
tunnel_plugins, statistics, debug,
|
31
|
+
processors, opts
|
32
|
+
)
|
30
33
|
@input = input
|
31
34
|
@output = output
|
32
35
|
@tunnel_plugins = tunnel_plugins
|
data/lib/ffwd/core/processor.rb
CHANGED
@@ -38,25 +38,24 @@ module FFWD
|
|
38
38
|
@emitter = emitter
|
39
39
|
@processors = processors
|
40
40
|
@reporters = reporters
|
41
|
-
|
42
|
-
subs = []
|
41
|
+
@subs = []
|
43
42
|
|
44
43
|
@processors.each do |name, p|
|
45
44
|
p.depend_on input
|
46
45
|
end
|
47
46
|
|
48
47
|
input.starting do
|
49
|
-
subs << input.metric_subscribe do |m|
|
48
|
+
@subs << input.metric_subscribe do |m|
|
50
49
|
process_metric m
|
51
50
|
end
|
52
51
|
|
53
|
-
subs << input.event_subscribe do |e|
|
52
|
+
@subs << input.event_subscribe do |e|
|
54
53
|
process_event e
|
55
54
|
end
|
56
55
|
end
|
57
56
|
|
58
57
|
input.stopping do
|
59
|
-
subs.each(&:unsubscribe).clear
|
58
|
+
@subs.each(&:unsubscribe).clear
|
60
59
|
end
|
61
60
|
end
|
62
61
|
|
@@ -17,10 +17,7 @@ require_relative '../lifecycle'
|
|
17
17
|
|
18
18
|
module FFWD::Debug
|
19
19
|
class MonitorSession
|
20
|
-
|
21
|
-
|
22
|
-
def initialize id, channel, type
|
23
|
-
@id = id
|
20
|
+
def initialize channel, type
|
24
21
|
@type = type
|
25
22
|
@clients = {}
|
26
23
|
|
@@ -31,7 +28,7 @@ module FFWD::Debug
|
|
31
28
|
data = @type.serialize_event event
|
32
29
|
|
33
30
|
begin
|
34
|
-
send JSON.dump(:id =>
|
31
|
+
send JSON.dump(:id => channel.id, :type => :event, :data => data)
|
35
32
|
rescue => e
|
36
33
|
log.error "Failed to serialize event", e
|
37
34
|
return
|
@@ -42,7 +39,7 @@ module FFWD::Debug
|
|
42
39
|
data = @type.serialize_metric metric
|
43
40
|
|
44
41
|
begin
|
45
|
-
send JSON.dump(:id =>
|
42
|
+
send JSON.dump(:id => channel.id, :type => :metric, :data => data)
|
46
43
|
rescue => e
|
47
44
|
log.error "Failed to serialize metric", e
|
48
45
|
return
|
data/lib/ffwd/debug/tcp.rb
CHANGED
@@ -31,14 +31,15 @@ module FFWD::Debug
|
|
31
31
|
@host = host
|
32
32
|
@port = port
|
33
33
|
@peer = "#{@host}:#{@port}"
|
34
|
+
info = "tcp://#{@peer}"
|
34
35
|
|
35
36
|
r = FFWD.retry :timeout => rebind_timeout do |attempt|
|
36
37
|
EM.start_server @host, @port, Connection, self
|
37
|
-
log.info "Bind on
|
38
|
+
log.info "Bind on #{info} (attempt #{attempt})"
|
38
39
|
end
|
39
40
|
|
40
41
|
r.error do |a, t, e|
|
41
|
-
log.
|
42
|
+
log.warning "Bind on #{info} failed, retry ##{a} in #{t}s: #{e}"
|
42
43
|
end
|
43
44
|
|
44
45
|
r.depend_on self
|
@@ -61,21 +62,25 @@ module FFWD::Debug
|
|
61
62
|
end
|
62
63
|
|
63
64
|
# Setup monitor hooks for the specified input and output channel.
|
64
|
-
def monitor
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
def monitor channel, type
|
66
|
+
channel.starting do
|
67
|
+
if session = @sessions[channel.id]
|
68
|
+
log.error "Session already monitored: #{channel.id}"
|
69
|
+
return
|
70
|
+
end
|
69
71
|
|
70
|
-
|
72
|
+
session = MonitorSession.new channel, type
|
71
73
|
|
72
|
-
|
73
|
-
|
74
|
-
|
74
|
+
# provide the session to any already connected clients.
|
75
|
+
@clients.each do |peer, client|
|
76
|
+
session.register peer, client
|
77
|
+
end
|
78
|
+
|
79
|
+
@sessions[channel.id] = session
|
75
80
|
end
|
76
81
|
|
77
82
|
channel.stopping do
|
78
|
-
@sessions.delete id
|
83
|
+
@sessions.delete channel.id
|
79
84
|
end
|
80
85
|
end
|
81
86
|
end
|
data/lib/ffwd/handler.rb
CHANGED
data/lib/ffwd/plugin.rb
CHANGED
@@ -28,7 +28,6 @@ module FFWD
|
|
28
28
|
@options = config[:options]
|
29
29
|
@setup_input_method = load_method @mod, config[:setup_input_method_name]
|
30
30
|
@setup_output_method = load_method @mod, config[:setup_output_method_name]
|
31
|
-
@setup_tunnel_method = load_method @mod, config[:setup_tunnel_method_name]
|
32
31
|
end
|
33
32
|
|
34
33
|
def capabilities
|
@@ -42,10 +41,6 @@ module FFWD
|
|
42
41
|
capabilities << "output"
|
43
42
|
end
|
44
43
|
|
45
|
-
if not @setup_tunnel_method.nil?
|
46
|
-
capabilities << "tunnel"
|
47
|
-
end
|
48
|
-
|
49
44
|
return capabilities
|
50
45
|
end
|
51
46
|
|
@@ -56,7 +51,6 @@ module FFWD
|
|
56
51
|
def get(kind)
|
57
52
|
return @setup_input_method if kind == :input
|
58
53
|
return @setup_output_method if kind == :output
|
59
|
-
return @setup_tunnel_method if kind == :tunnel
|
60
54
|
return nil
|
61
55
|
end
|
62
56
|
|
@@ -69,16 +63,16 @@ module FFWD
|
|
69
63
|
end
|
70
64
|
|
71
65
|
class Setup
|
72
|
-
attr_reader :
|
66
|
+
attr_reader :config, :name
|
73
67
|
|
74
|
-
def initialize
|
75
|
-
@
|
68
|
+
def initialize method, config, name
|
69
|
+
@method = method
|
76
70
|
@config = config
|
77
|
-
@
|
71
|
+
@name = name
|
78
72
|
end
|
79
73
|
|
80
|
-
def
|
81
|
-
@
|
74
|
+
def call *args
|
75
|
+
@method.call(*args)
|
82
76
|
end
|
83
77
|
end
|
84
78
|
|
@@ -100,7 +94,6 @@ module FFWD
|
|
100
94
|
|
101
95
|
config[:setup_input_method_name] = (opts[:setup_input_method] || :setup_input)
|
102
96
|
config[:setup_output_method_name] = (opts[:setup_output_method] || :setup_output)
|
103
|
-
config[:setup_tunnel_method_name] = (opts[:setup_tunnel_method] || :setup_tunnel)
|
104
97
|
|
105
98
|
FFWD::Plugin.discovered[name] = config
|
106
99
|
end
|
@@ -122,7 +115,7 @@ module FFWD
|
|
122
115
|
FFWD::Plugin.discovered.clear
|
123
116
|
end
|
124
117
|
|
125
|
-
def self.load_plugins log, kind_name, config, kind
|
118
|
+
def self.load_plugins log, kind_name, config, kind, m
|
126
119
|
result = []
|
127
120
|
|
128
121
|
return result if config.nil?
|
@@ -145,7 +138,19 @@ module FFWD
|
|
145
138
|
next
|
146
139
|
end
|
147
140
|
|
148
|
-
|
141
|
+
factory = setup.call Hash[plugin_config]
|
142
|
+
|
143
|
+
unless factory.respond_to? m
|
144
|
+
log.error "#{d}: Plugin '#{name}' does not support '#{m.to_s}'"
|
145
|
+
next
|
146
|
+
end
|
147
|
+
|
148
|
+
unless factory.respond_to? :config
|
149
|
+
log.error "#{d}: Plugin '#{name}' does not support 'config'"
|
150
|
+
next
|
151
|
+
end
|
152
|
+
|
153
|
+
result << Setup.new(factory.method(m), factory.config, name)
|
149
154
|
end
|
150
155
|
|
151
156
|
return result
|
data/lib/ffwd/plugin/json.rb
CHANGED
@@ -50,9 +50,7 @@ module FFWD::Plugin::JSON
|
|
50
50
|
])
|
51
51
|
]
|
52
52
|
|
53
|
-
class LineConnection < FFWD::Connection
|
54
|
-
include FFWD::Logging
|
55
|
-
include FFWD::Plugin::JSON::Connection
|
53
|
+
class LineConnection < FFWD::Plugin::JSON::Connection
|
56
54
|
include EM::Protocols::LineText2
|
57
55
|
|
58
56
|
def self.plugin_type
|
@@ -64,10 +62,7 @@ module FFWD::Plugin::JSON
|
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
67
|
-
class FrameConnection < FFWD::Connection
|
68
|
-
include FFWD::Logging
|
69
|
-
include FFWD::Plugin::JSON::Connection
|
70
|
-
|
65
|
+
class FrameConnection < FFWD::Plugin::JSON::Connection
|
71
66
|
def self.plugin_type
|
72
67
|
"json_frame_in"
|
73
68
|
end
|
@@ -79,13 +74,18 @@ module FFWD::Plugin::JSON
|
|
79
74
|
|
80
75
|
KINDS = {"frame" => FrameConnection, "line" => LineConnection}
|
81
76
|
|
82
|
-
def self.setup_input opts
|
83
|
-
kind = (opts[:kind] || DEFAULT_KIND).to_s
|
84
|
-
raise "No such kind: #{kind}" unless connection = KINDS[kind]
|
85
|
-
protocol = FFWD.parse_protocol opts[:protocol] || DEFAULT_PROTOCOL[kind]
|
77
|
+
def self.setup_input opts
|
86
78
|
opts[:host] ||= DEFAULT_HOST
|
87
79
|
opts[:port] ||= DEFAULT_PORT
|
88
80
|
|
81
|
+
kind = (opts[:kind] || DEFAULT_KIND).to_s
|
82
|
+
|
83
|
+
unless connection = KINDS[kind]
|
84
|
+
raise "No such protocol kind: #{kind}"
|
85
|
+
end
|
86
|
+
|
87
|
+
protocol = FFWD.parse_protocol opts[:protocol] || DEFAULT_PROTOCOL[kind]
|
88
|
+
|
89
89
|
if connection == FrameConnection and protocol != FFWD::UDP
|
90
90
|
log.warning "When using :frame kind, you should use the UDP protocol." +
|
91
91
|
" Not #{protocol.family.to_s.upcase}"
|
@@ -96,14 +96,6 @@ module FFWD::Plugin::JSON
|
|
96
96
|
"Not #{protocol.family.to_s.upcase}"
|
97
97
|
end
|
98
98
|
|
99
|
-
protocol.bind opts,
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.setup_tunnel opts, core, tunnel
|
103
|
-
protocol = FFWD.parse_protocol opts[:protocol] || "tcp"
|
104
|
-
kind = (opts[:kind] || DEFAULT_KIND).to_s
|
105
|
-
raise "No such kind: #{kind}" unless connection = KINDS[kind]
|
106
|
-
opts[:port] ||= DEFAULT_PORT
|
107
|
-
protocol.tunnel opts, core, tunnel, log, connection
|
99
|
+
protocol.bind opts, log, connection
|
108
100
|
end
|
109
101
|
end
|