ffwd 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/ffwd/logging.rb
ADDED
@@ -0,0 +1,139 @@
|
|
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
|
+
# Logging functionality.
|
17
|
+
#
|
18
|
+
# Defines FFWD::Logging which when included in either a class or module makes
|
19
|
+
# the 'log' field available both as a class and instance field.
|
20
|
+
#
|
21
|
+
# 'log' in turn is an object with the following fields available.
|
22
|
+
#
|
23
|
+
# 'debug' - Log a message of level DEBUG..
|
24
|
+
# 'info' - Log a message of level INFO.
|
25
|
+
# 'warning' - Log a message of level WARNING.
|
26
|
+
# 'error' - Log a message of level ERROR.
|
27
|
+
#
|
28
|
+
# Every function takes the message to log as the only parameter except 'error'
|
29
|
+
# which can take an exception as a secondary argument.
|
30
|
+
#
|
31
|
+
# If an exception is provided, a stacktrace will be printed to log.
|
32
|
+
require 'logger'
|
33
|
+
|
34
|
+
module FFWD
|
35
|
+
def self.log
|
36
|
+
@log ||= setup_log
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.log_reload
|
40
|
+
@log = setup_log
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.setup_log
|
44
|
+
if log_config[:file]
|
45
|
+
file = log_config[:file]
|
46
|
+
shift_age = log_config[:shift_age]
|
47
|
+
|
48
|
+
return ::Logger.new(file, shift_age=shift_age).tap do |l|
|
49
|
+
l.level = log_config[:level]
|
50
|
+
l.progname = log_config[:progname]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if log_config[:stream]
|
55
|
+
return ::Logger.new(log_config[:stream]).tap do |l|
|
56
|
+
l.level = log_config[:level]
|
57
|
+
l.progname = log_config[:progname]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
raise "cannot setup loggin with options: #{log_config}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.log_config
|
65
|
+
return @log_config unless @log_config.nil?
|
66
|
+
|
67
|
+
@log_config = {
|
68
|
+
:file => nil,
|
69
|
+
:shift_age => 1,
|
70
|
+
:level => Logger::INFO,
|
71
|
+
:stream => STDOUT,
|
72
|
+
:progname => 'FFWD',
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.log_disable
|
77
|
+
@log_disable = true
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.log_disabled?
|
81
|
+
@log_disable || false
|
82
|
+
end
|
83
|
+
|
84
|
+
class ClassLogger
|
85
|
+
def initialize klass
|
86
|
+
@progname = klass.name
|
87
|
+
end
|
88
|
+
|
89
|
+
def debug message
|
90
|
+
FFWD.log.debug(@progname){message}
|
91
|
+
end
|
92
|
+
|
93
|
+
def info message
|
94
|
+
FFWD.log.info(@progname){message}
|
95
|
+
end
|
96
|
+
|
97
|
+
def warning message
|
98
|
+
FFWD.log.warn(@progname){message}
|
99
|
+
end
|
100
|
+
|
101
|
+
def error message, e=nil
|
102
|
+
FFWD.log.error(@progname){message}
|
103
|
+
|
104
|
+
return unless e
|
105
|
+
|
106
|
+
FFWD.log.error(@progname){"Caused by #{e.class}: #{e}"}
|
107
|
+
e.backtrace.each do |b|
|
108
|
+
FFWD.log.error(@progname){" #{b}"}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class FakeLogger
|
114
|
+
def debug message; end
|
115
|
+
def info message; end
|
116
|
+
def warning message; end
|
117
|
+
def error message, e=nil; end
|
118
|
+
end
|
119
|
+
|
120
|
+
module Logging
|
121
|
+
module ClassMethods
|
122
|
+
attr_accessor :log
|
123
|
+
end
|
124
|
+
|
125
|
+
def log
|
126
|
+
self.class.log
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.included klass
|
130
|
+
klass.extend ClassMethods
|
131
|
+
|
132
|
+
if FFWD.log_disabled?
|
133
|
+
klass.log = FakeLogger.new
|
134
|
+
else
|
135
|
+
klass.log = ClassLogger.new klass
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/ffwd/metric.rb
ADDED
@@ -0,0 +1,55 @@
|
|
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
|
+
module FFWD
|
17
|
+
# Struct used to define all fields related to a metric.
|
18
|
+
MetricStruct = Struct.new(
|
19
|
+
# The time at which the metric was collected.
|
20
|
+
:time,
|
21
|
+
# The unique key of the metric.
|
22
|
+
:key,
|
23
|
+
# A numeric value associated with the metric.
|
24
|
+
:value,
|
25
|
+
# The host from which the metric originated.
|
26
|
+
:host,
|
27
|
+
# The source metric this metric was derived from (if any).
|
28
|
+
:source,
|
29
|
+
# Tags associated to the metric.
|
30
|
+
:tags,
|
31
|
+
# Attributes (extra fields) associated to the metric.
|
32
|
+
:attributes
|
33
|
+
)
|
34
|
+
|
35
|
+
# A convenience class for each individual metric.
|
36
|
+
class Metric < MetricStruct
|
37
|
+
def self.make opts={}
|
38
|
+
new(opts[:time], opts[:key], opts[:value], opts[:host], opts[:source],
|
39
|
+
opts[:tags], opts[:attributes])
|
40
|
+
end
|
41
|
+
|
42
|
+
# Convert metric to a sparse hash.
|
43
|
+
def to_h
|
44
|
+
d = {}
|
45
|
+
d[:time] = time.to_i if time
|
46
|
+
d[:key] = key if key
|
47
|
+
d[:value] = value if value
|
48
|
+
d[:host] = host if host
|
49
|
+
d[:source] = source if source
|
50
|
+
d[:tags] = tags.to_a if tags
|
51
|
+
d[:attributes] = attributes if attributes
|
52
|
+
d
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,50 @@
|
|
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 'utils'
|
17
|
+
require_relative 'metric'
|
18
|
+
|
19
|
+
module FFWD
|
20
|
+
# Used to emit metrics to an 'output' channel
|
21
|
+
#
|
22
|
+
# Can take two parts of a configuration 'base' and 'opts' to decide which
|
23
|
+
# metadata emitted metrics should be decorated with.
|
24
|
+
class MetricEmitter
|
25
|
+
def self.build output, base, opts
|
26
|
+
host = opts[:host] || base[:host] || FFWD.current_host
|
27
|
+
tags = FFWD.merge_sets base[:tags], opts[:tags]
|
28
|
+
attributes = FFWD.merge_hashes base[:attributes], opts[:attributes]
|
29
|
+
new output, host, tags, attributes
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize output, host, tags, attributes
|
33
|
+
@output = output
|
34
|
+
@host = host
|
35
|
+
@tags = tags
|
36
|
+
@attributes = attributes
|
37
|
+
end
|
38
|
+
|
39
|
+
def emit m
|
40
|
+
m[:time] ||= Time.now
|
41
|
+
m[:host] ||= @host if @host
|
42
|
+
m[:tags] = FFWD.merge_sets @tags, m[:tags]
|
43
|
+
m[:attributes] = FFWD.merge_hashes @attributes, m[:attributes]
|
44
|
+
|
45
|
+
@output.metric Metric.make(m)
|
46
|
+
rescue => e
|
47
|
+
log.error "Failed to emit metric", e
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/ffwd/plugin.rb
ADDED
@@ -0,0 +1,149 @@
|
|
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 'logging'
|
17
|
+
|
18
|
+
module FFWD
|
19
|
+
module Plugin
|
20
|
+
class Loaded
|
21
|
+
attr_reader :source, :name
|
22
|
+
|
23
|
+
def initialize source, name, options
|
24
|
+
@source = source
|
25
|
+
@name = name
|
26
|
+
@mod = options[:mod]
|
27
|
+
@setup_input_method = load_method @mod, options[:setup_input_method_name]
|
28
|
+
@setup_output_method = load_method @mod, options[:setup_output_method_name]
|
29
|
+
@setup_tunnel_method = load_method @mod, options[:setup_tunnel_method_name]
|
30
|
+
end
|
31
|
+
|
32
|
+
def capabilities
|
33
|
+
capabilities = []
|
34
|
+
|
35
|
+
if not @setup_input_method.nil?
|
36
|
+
capabilities << "input"
|
37
|
+
end
|
38
|
+
|
39
|
+
if not @setup_output_method.nil?
|
40
|
+
capabilities << "output"
|
41
|
+
end
|
42
|
+
|
43
|
+
if not @setup_tunnel_method.nil?
|
44
|
+
capabilities << "tunnel"
|
45
|
+
end
|
46
|
+
|
47
|
+
return capabilities
|
48
|
+
end
|
49
|
+
|
50
|
+
def can?(kind)
|
51
|
+
not get(kind).nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
def get(kind)
|
55
|
+
return @setup_input_method if kind == :input
|
56
|
+
return @setup_output_method if kind == :output
|
57
|
+
return @setup_tunnel_method if kind == :tunnel
|
58
|
+
return nil
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def load_method mod, method_name
|
64
|
+
return nil unless mod.respond_to? method_name
|
65
|
+
return mod.method method_name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class Setup
|
70
|
+
attr_reader :name, :config
|
71
|
+
|
72
|
+
def initialize name, setup, config
|
73
|
+
@name = name
|
74
|
+
@setup = setup
|
75
|
+
@config = config
|
76
|
+
end
|
77
|
+
|
78
|
+
def setup *args
|
79
|
+
@setup.call @config, *args
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.discovered
|
84
|
+
@@discovered ||= {}
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.loaded
|
88
|
+
@@loaded ||= {}
|
89
|
+
end
|
90
|
+
|
91
|
+
module ClassMethods
|
92
|
+
def register_plugin(name, opts={})
|
93
|
+
options = {:mod => self}
|
94
|
+
|
95
|
+
options[:setup_input_method_name] = (opts[:setup_input_method] || :setup_input)
|
96
|
+
options[:setup_output_method_name] = (opts[:setup_output_method] || :setup_output)
|
97
|
+
options[:setup_tunnel_method_name] = (opts[:setup_tunnel_method] || :setup_tunnel)
|
98
|
+
|
99
|
+
FFWD::Plugin.discovered[name] = options
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.included mod
|
104
|
+
mod.extend ClassMethods
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.category
|
108
|
+
'plugin'
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.load_discovered source
|
112
|
+
FFWD::Plugin.discovered.each do |name, options|
|
113
|
+
FFWD::Plugin.loaded[name] = Loaded.new source, name, options
|
114
|
+
end
|
115
|
+
|
116
|
+
FFWD::Plugin.discovered.clear
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.load_plugins log, kind_name, config, kind
|
120
|
+
result = []
|
121
|
+
|
122
|
+
if config.nil?
|
123
|
+
return result
|
124
|
+
end
|
125
|
+
|
126
|
+
config.each_with_index do |plugin_config, index|
|
127
|
+
d = "#{kind_name} plugin ##{index}"
|
128
|
+
|
129
|
+
if (name = plugin_config[:type]).nil?
|
130
|
+
log.error "#{d}: Missing :type attribute for '#{kind_name}'"
|
131
|
+
end
|
132
|
+
|
133
|
+
if (plugin = FFWD::Plugin.loaded[name]).nil?
|
134
|
+
log.error "#{d}: Not an available plugin '#{name}'"
|
135
|
+
next
|
136
|
+
end
|
137
|
+
|
138
|
+
unless plugin.can?(kind)
|
139
|
+
log.error "#{d}: Not an #{kind_name} plugin '#{name}'"
|
140
|
+
next
|
141
|
+
end
|
142
|
+
|
143
|
+
result << Setup.new(name, plugin.get(kind), plugin_config)
|
144
|
+
end
|
145
|
+
|
146
|
+
return result
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,47 @@
|
|
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 'eventmachine'
|
17
|
+
|
18
|
+
require 'ffwd/protocol'
|
19
|
+
require 'ffwd/plugin'
|
20
|
+
require 'ffwd/logging'
|
21
|
+
|
22
|
+
require_relative 'json_line/connection'
|
23
|
+
|
24
|
+
module FFWD::Plugin::JsonLine
|
25
|
+
include FFWD::Plugin
|
26
|
+
include FFWD::Logging
|
27
|
+
|
28
|
+
register_plugin "json_line"
|
29
|
+
|
30
|
+
DEFAULT_HOST = "localhost"
|
31
|
+
DEFAULT_PORT = 19000
|
32
|
+
|
33
|
+
def self.setup_input opts, core
|
34
|
+
opts[:host] ||= DEFAULT_HOST
|
35
|
+
opts[:port] ||= DEFAULT_PORT
|
36
|
+
buffer_limit = opts["buffer_limit"] || 1000
|
37
|
+
protocol = FFWD.parse_protocol(opts[:protocol] || "tcp")
|
38
|
+
protocol.bind opts, core, log, Connection, buffer_limit
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.setup_tunnel opts, core, tunnel
|
42
|
+
opts[:port] ||= DEFAULT_PORT
|
43
|
+
buffer_limit = opts["buffer_limit"] || 1000
|
44
|
+
protocol = FFWD.parse_protocol(opts[:protocol] || "tcp")
|
45
|
+
protocol.tunnel opts, core, tunnel, log, Connection, buffer_limit
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,118 @@
|
|
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 'eventmachine'
|
17
|
+
|
18
|
+
require 'ffwd/logging'
|
19
|
+
require 'ffwd/connection'
|
20
|
+
|
21
|
+
module FFWD::Plugin::JsonLine
|
22
|
+
class Connection < FFWD::Connection
|
23
|
+
include FFWD::Logging
|
24
|
+
include EM::Protocols::LineText2
|
25
|
+
|
26
|
+
EVENT_FIELDS = [
|
27
|
+
["key", :key],
|
28
|
+
["value", :value],
|
29
|
+
["host", :host],
|
30
|
+
["state", :state],
|
31
|
+
["description", :description],
|
32
|
+
["ttl", :ttl],
|
33
|
+
["tags", :tags],
|
34
|
+
["attributes", :attributes],
|
35
|
+
]
|
36
|
+
|
37
|
+
METRIC_FIELDS = [
|
38
|
+
["proc", :proc],
|
39
|
+
["key", :key],
|
40
|
+
["value", :value],
|
41
|
+
["tags", :tags],
|
42
|
+
["attributes", :attributes]
|
43
|
+
]
|
44
|
+
|
45
|
+
def self.plugin_type
|
46
|
+
"json_line_in"
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize bind, core, buffer_limit
|
50
|
+
@bind = bind
|
51
|
+
@core = core
|
52
|
+
@buffer_limit = buffer_limit
|
53
|
+
end
|
54
|
+
|
55
|
+
def receive_line data
|
56
|
+
data = JSON.load(data)
|
57
|
+
|
58
|
+
unless type = data["type"]
|
59
|
+
log.error "Field 'type' missing from received line"
|
60
|
+
return
|
61
|
+
end
|
62
|
+
|
63
|
+
if type == "metric"
|
64
|
+
@core.input.metric read_metric(data)
|
65
|
+
@bind.increment :received_metric
|
66
|
+
return
|
67
|
+
end
|
68
|
+
|
69
|
+
if type == "event"
|
70
|
+
@core.input.event read_event(data)
|
71
|
+
@bind.increment :received_event
|
72
|
+
return
|
73
|
+
end
|
74
|
+
|
75
|
+
log.error "No such type: #{type}"
|
76
|
+
rescue => e
|
77
|
+
log.error "Failed to receive line", e
|
78
|
+
end
|
79
|
+
|
80
|
+
def read_tags d, source
|
81
|
+
return if (tags = d["tags"]).nil?
|
82
|
+
d[:tags] = tags.to_set
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_time d, source
|
86
|
+
return if (time = d["time"]).nil?
|
87
|
+
d[:time] = Time.at time
|
88
|
+
end
|
89
|
+
|
90
|
+
def read_metric data
|
91
|
+
d = {}
|
92
|
+
|
93
|
+
read_tags d, data["tags"]
|
94
|
+
read_time d, data["time"]
|
95
|
+
|
96
|
+
METRIC_FIELDS.each do |from, to|
|
97
|
+
next if (v = data[from]).nil?
|
98
|
+
d[to] = v
|
99
|
+
end
|
100
|
+
|
101
|
+
d
|
102
|
+
end
|
103
|
+
|
104
|
+
def read_event data
|
105
|
+
d = {}
|
106
|
+
|
107
|
+
read_tags d, data["tags"]
|
108
|
+
read_time d, data["time"]
|
109
|
+
|
110
|
+
EVENT_FIELDS.each do |from, to|
|
111
|
+
next if (v = data[from]).nil?
|
112
|
+
d[to] = v
|
113
|
+
end
|
114
|
+
|
115
|
+
d
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|