anschel 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c067fd0f07d2642121198aed3e1a129c753ed34
4
- data.tar.gz: 4c404083a4512a68bbe8f84683e6d89dd47e3acd
3
+ metadata.gz: 6a2475c658cf220a706e32d1bd87816b1278465d
4
+ data.tar.gz: b6a9b99ff3ce1b8829373c1abc08809f9b0e7660
5
5
  SHA512:
6
- metadata.gz: 62fd8c2b1775ae0d938473fd706d2520d5f6dfa6573184f540e0fff7f3d91dacd93e18ca4fdfc2da06d89b13eba830248d163293b7c0aed744055e898014ebf6
7
- data.tar.gz: 2f986177c04b3a24af8c48966f270b8bed5d94b26db59147f866b98f91b493c4b552de21a23e54e11d8c842ede68a345ac06e6c07ab374fd32039049dc70a9e5
6
+ metadata.gz: 5e6882bb74eb0f96074c0a126c67eb9151d49ad64ab094fc91089cbdc9e3ae5d8603748b21e3190c6192defea4885d2517f632270dde4ac5a38ac3efc4a65e95
7
+ data.tar.gz: fd482f04a614e36a9f75a104e77ed52f2905e80730a35aabe485d8c2cce20918283eec6a2e447c9c3ff9b0dc347c41cd19107ae1c1a8020f6d5f5e215ef18f24
data/Readme.md CHANGED
@@ -162,4 +162,6 @@ You might deploy Anschel with Upstart. Here's a minimal config:
162
162
  _In development_
163
163
 
164
164
  - Intial implementation of the Kafka-to-Elasticsearch pipeline
165
- - Additional support for RabbitMQ input and file (device) output
165
+ - Support for file (device) output (v0.4)
166
+ - Support for RabbitMQ input (v0.5)
167
+ - Allow multiple input and output configuration (v0.6)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -2,7 +2,8 @@
2
2
  # "index": {
3
3
  # "stamp": "",
4
4
  # "prefix": "",
5
- # "suffix": ""
5
+ # "suffix": "",
6
+ # "format": ""
6
7
  # }
7
8
  # }
8
9
  module Anschel
@@ -11,18 +12,17 @@ module Anschel
11
12
  stamp = conf.delete(:stamp) || '@timestamp'
12
13
  prefix = conf.delete(:prefix) || 'logs-%{type}-'
13
14
  suffix = conf.delete(:suffix) || '%Y.%m.%d'
15
+ format = conf.delete(:format) || "yyyy-MM-dd'T'HH:mm:ss.SSSZ" # ISO8601
14
16
 
15
17
  stamp = stamp.to_sym
16
18
 
17
- iso8601 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
18
-
19
- joda = org.joda.time.format.DateTimeFormat.forPattern iso8601
19
+ joda = org.joda.time.format.DateTimeFormat.forPattern format
20
20
  joda = joda.withDefaultYear(Time.new.year)
21
21
  joda = joda.withOffsetParsed
22
22
 
23
23
 
24
24
  log.debug event: 'compiled-filter', filter: 'index', \
25
- stamp: stamp, prefix: prefix, suffix: suffix
25
+ stamp: stamp, prefix: prefix, suffix: suffix, format: format
26
26
 
27
27
  lambda do |event|
28
28
  return event unless event.has_key? stamp
@@ -23,7 +23,7 @@ module Anschel
23
23
  return event unless event.has_key? field
24
24
  mdata = pattern.match event[field]
25
25
  mdata.names.each do |group|
26
- event[group] = mdata[group]
26
+ event[group.to_sym] = mdata[group]
27
27
  end
28
28
  filtered event, conf
29
29
  end
@@ -28,7 +28,7 @@ module Anschel
28
28
 
29
29
  def apply event
30
30
  raise 'Event does not have a "type" field' unless event[:type]
31
- type = event[:type].dup # In case of modification
31
+ type = event[:type].to_sym # In case of modification
32
32
  filters[:_before].each { |f| f.call event }
33
33
  filters[type].each { |f| f.call event }
34
34
  filters[:_after].each { |f| f.call event }
@@ -40,7 +40,7 @@ module Anschel
40
40
 
41
41
  def filtered event, options
42
42
  if remove_field = options[:remove_field]
43
- event.delete remove_field
43
+ event.delete remove_field.to_sym
44
44
  end
45
45
  event
46
46
  end
@@ -0,0 +1,9 @@
1
+ module Anschel
2
+ class Input
3
+ class Base
4
+ def stop
5
+ raise 'To be implemented'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,27 +1,22 @@
1
1
  require 'jruby-kafka'
2
2
 
3
+ require_relative 'base'
4
+
3
5
 
4
6
  module Anschel
5
7
  class Input
6
- class Kafka
7
- def initialize config, stats, log
8
+ class Kafka < Base
9
+ def initialize queue, config, stats, log
8
10
  log.trace event: 'input', kind: 'kafka', config: config
9
- qsize = config.delete(:queue_size) || 1000
10
- @queue = SizedQueue.new qsize
11
- consumer_group = ::Kafka::Group.new config
12
- consumer_group.run num_cpus, @queue
13
-
14
- trap('SIGINT') do
15
- consumer_group.shutdown
16
- log.info event: 'goodbye', version: VERSION
17
- exit
18
- end
19
-
20
- log.info event: 'input-loaded'
11
+ @consumer_group = ::Kafka::Group.new config
12
+ @consumer_group.run num_cpus, queue
21
13
  end
22
14
 
23
-
24
- def shift ; @queue.shift end
15
+ def stop
16
+ return if @stopped
17
+ @consumer_group.shutdown
18
+ @stopped = true
19
+ end
25
20
  end
26
21
  end
27
22
  end
@@ -1,15 +1,18 @@
1
1
  require 'march_hare'
2
2
 
3
+ require_relative 'base'
4
+
3
5
 
4
6
  module Anschel
5
7
  class Input
6
- class RabbitMQ
7
- def initialize config, stats, log
8
+ class RabbitMQ < Base
9
+ def initialize queue, config, stats, log
8
10
  log.trace event: 'input', kind: 'rabbitmq', config: config
9
- qsize = config[:connection].delete(:queue_size) || 1000
10
- @queue = SizedQueue.new qsize
11
11
 
12
- default_exchange = { type: 'x-consistent-hash' }
12
+ default_exchange = {
13
+ type: 'x-consistent-hash',
14
+ durable: true
15
+ }
13
16
 
14
17
  default_qconf = {
15
18
  exclusive: false,
@@ -19,34 +22,27 @@ module Anschel
19
22
 
20
23
  exchange_name = config[:exchange].delete(:name)
21
24
 
22
- rmq_threads = config[:queues].map do |qname, qconf|
25
+ @threads = config[:queues].map do |qname, qconf|
23
26
  Thread.new do
24
27
  conn = ::MarchHare.connect config[:connection]
25
28
  chan = conn.create_channel
26
29
 
27
- exchange = channel.exchange exchange_name, \
30
+ exchange = chan.exchange exchange_name, \
28
31
  default_exchange.merge(config[:exchange])
29
32
 
30
- rmq = chan.queue qname, default_qconf.merge(qconf)
31
- rmq.subscribe(block: true, ack: true) do |_, message|
32
- @queue << message
33
+ rmq = chan.queue qname.to_s, default_qconf.merge(qconf)
34
+ rmq.subscribe(block: true) do |_, message|
35
+ queue << message
33
36
  end
34
37
  end
35
38
  end
36
-
37
- trap('SIGINT') do
38
- rmq_threads.map &:kill
39
- log.info event: 'goodbye', version: VERSION
40
- exit
41
- end
42
-
43
- log.info event: 'input-loaded'
44
-
45
- rmq_threads.map &:join
46
39
  end
47
40
 
48
-
49
- def shift ; @queue.shift end
41
+ def stop
42
+ return if @stopped
43
+ @threads.map &:kill
44
+ @stopped = true
45
+ end
50
46
  end
51
47
  end
52
48
  end
data/lib/anschel/input.rb CHANGED
@@ -4,13 +4,44 @@ require_relative 'input/rabbitmq'
4
4
 
5
5
  module Anschel
6
6
  class Input
7
- def initialize config, stats, log
8
- if config[:kafka]
9
- Input::Kafka.new config[:kafka], stats, log
10
- elsif config[:rabbitmq]
11
- Input::RabbitMQ.new config[:rabbitmq], stats, log
7
+ def initialize config, qsize, stats, log
8
+ if config.empty?
9
+ raise 'No input provided'
10
+ end
11
+
12
+ @queue = SizedQueue.new qsize || 2000
13
+
14
+ @inputs = []
15
+
16
+ config.each do |input|
17
+ case input.delete(:kind)
18
+ when 'kafka'
19
+ @inputs << Input::Kafka.new(@queue, input, stats, log)
20
+ when 'rabbitmq'
21
+ @inputs << Input::RabbitMQ.new(@queue, input, stats, log)
22
+ else
23
+ raise 'Uknown input type'
24
+ end
25
+ end
26
+
27
+ log.info event: 'input-loaded'
28
+ end
29
+
30
+
31
+ def stop
32
+ return if @stopped
33
+ @inputs.map &:stop
34
+ @stopped = true
35
+ end
36
+
37
+
38
+ def shift
39
+ event = @queue.shift
40
+ case event
41
+ when String
42
+ event
12
43
  else
13
- raise 'Unkown input type'
44
+ event.message.to_s
14
45
  end
15
46
  end
16
47
  end
data/lib/anschel/main.rb CHANGED
@@ -46,17 +46,27 @@ module Anschel
46
46
  options: options.to_hash,
47
47
  num_cpus: num_cpus
48
48
 
49
- config = JrJackson::Json.load File.read(options.config), symbolize_keys: true
49
+ config = JrJackson::Json.load \
50
+ File.read(options.config), symbolize_keys: true
51
+
50
52
  setup_log4j config[:log4j]
51
53
 
52
54
  stats = Stats.new log, options.stats_interval
53
55
 
54
- input = Input.new config[:input], stats, log
56
+ input = Input.new config[:input], config[:queue_size], stats, log
55
57
 
56
58
  filter = Filter.new config[:filter], stats, log
57
59
 
58
60
  output = Output.new config[:output], stats, log
59
61
 
62
+ trap('SIGINT') do
63
+ input.stop
64
+ output.stop
65
+ log.info event: 'goodbye', version: VERSION
66
+ exit
67
+ end
68
+
69
+
60
70
  stats.create 'event'
61
71
  stats.get 'event'
62
72
 
@@ -64,7 +74,7 @@ module Anschel
64
74
  Thread.new do
65
75
  loop do
66
76
  event = JrJackson::Json.load \
67
- input.shift.message.to_s, symbolize_keys: true
77
+ input.shift, symbolize_keys: true
68
78
  output.push filter.apply(event)
69
79
  stats.inc 'event'
70
80
  end
@@ -0,0 +1,13 @@
1
+ module Anschel
2
+ class Output
3
+ class Base
4
+ def stop
5
+ return if @stopped
6
+ @thread.kill
7
+ @stopped = true
8
+ end
9
+
10
+ def push event ; @queue.push event end
11
+ end
12
+ end
13
+ end
@@ -1,27 +1,26 @@
1
1
  require 'thread'
2
2
 
3
+ require_relative 'base'
4
+
5
+
3
6
  module Anschel
4
7
  class Output
5
- class Device
8
+ class Device < Base
6
9
  def initialize config, stats, log
7
10
  log.trace event: 'output', kind: 'device', config: config
8
11
 
9
- path = config.delete(:path)
10
- qsize = config.delete(:queue_size) || 2000
11
- @q = SizedQueue.new qsize
12
+ path = config.delete(:path)
13
+ qsize = config.delete(:queue_size) || 2000
14
+ @queue = SizedQueue.new qsize
12
15
 
13
- Thread.new do
16
+ @thread = Thread.new do
14
17
  File.open(path, 'w') do |f|
15
18
  loop do
16
- f.puts @q.shift
19
+ f.puts @queue.shift
17
20
  end
18
21
  end
19
22
  end
20
-
21
- log.info event: 'output-loaded'
22
23
  end
23
-
24
- def push event ; @q.push event end
25
24
  end
26
25
  end
27
26
  end
@@ -1,16 +1,17 @@
1
1
  require 'thread'
2
2
 
3
- require 'typhoeus/adapters/faraday'
4
3
  require 'typhoeus'
4
+ require 'typhoeus/adapters/faraday'
5
5
  require 'elasticsearch'
6
6
 
7
+ require_relative 'base'
8
+
7
9
 
8
10
  module Anschel
9
11
  class Output
10
- class Elasticsearch
12
+ class Elasticsearch < Base
11
13
  def initialize config, stats, log
12
14
  log.trace event: 'output', kind: 'elasticsearch', config: config
13
- pattern = config.delete(:index_pattern)
14
15
  qsize = config.delete(:queue_size) || 2000
15
16
  bsize = config.delete(:bulk_size) || 500
16
17
  timeout = config.delete(:bulk_timeout) || 0.5
@@ -20,7 +21,7 @@ module Anschel
20
21
 
21
22
  @queue = SizedQueue.new qsize
22
23
 
23
- Thread.new do
24
+ @thread = Thread.new do
24
25
  loop do
25
26
  events = []
26
27
  count = 0
@@ -43,11 +44,7 @@ module Anschel
43
44
  client.bulk body: body
44
45
  end
45
46
  end
46
-
47
- log.info event: 'output-loaded'
48
47
  end
49
-
50
- def push event ; @queue.push event end
51
48
  end
52
49
  end
53
50
  end
@@ -5,12 +5,36 @@ require_relative 'output/device'
5
5
  module Anschel
6
6
  class Output
7
7
  def initialize config, stats, log
8
- if config[:device]
9
- Output::Device.new config[:device], stats, log
10
- elsif config[:elasticsearch]
11
- Output::Elasticsearch.new config[:elasticsearch], stats, log
12
- else
13
- raise 'Unkown output type'
8
+ if config.empty?
9
+ raise 'No output provided'
10
+ end
11
+
12
+ @outputs = []
13
+
14
+ config.each do |output|
15
+ case output.delete(:kind)
16
+ when 'device'
17
+ @outputs << Output::Device.new(output, stats, log)
18
+ when 'elasticsearch'
19
+ @outputs << Output::Elasticsearch.new(output, stats, log)
20
+ else
21
+ raise 'Unkown output type'
22
+ end
23
+ end
24
+
25
+ log.info event: 'output-loaded'
26
+ end
27
+
28
+
29
+ def stop
30
+ return if @stopped
31
+ @outputs.map &:stop
32
+ @stopped = true
33
+ end
34
+
35
+ def push event
36
+ @outputs.each do |output|
37
+ output.push event
14
38
  end
15
39
  end
16
40
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anschel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Clemmer
@@ -128,12 +128,14 @@ files:
128
128
  - lib/anschel/filter/scan.rb
129
129
  - lib/anschel/filter/stamp.rb
130
130
  - lib/anschel/input.rb
131
+ - lib/anschel/input/base.rb
131
132
  - lib/anschel/input/kafka.rb
132
133
  - lib/anschel/input/rabbitmq.rb
133
134
  - lib/anschel/main.rb
134
135
  - lib/anschel/metadata.rb
135
136
  - lib/anschel/mjolnir.rb
136
137
  - lib/anschel/output.rb
138
+ - lib/anschel/output/base.rb
137
139
  - lib/anschel/output/device.rb
138
140
  - lib/anschel/output/elasticsearch.rb
139
141
  - lib/anschel/stats.rb