gelf2kafka 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f79e92751af9147fcde84f2ddff5627de86cccbc
4
+ data.tar.gz: 47b91830af26859fb69a9d23bd9f403b84ce7676
5
+ SHA512:
6
+ metadata.gz: c6c11384ba8b1fa55d1339a590c48fffc32b417d669dffc15dc82a54d22f01034a84d777bd75e53307de98c0afdde67322bef54b1d679e6a23dc0905d01be48c
7
+ data.tar.gz: 35d31bd4bd2bf54a873b88b8b1afb87e0c5f161c3d229270d21a32ce69f7accff17dc4fbea193daeba7ed3be4837cba1a568b469c320952ba8d897393a4902fb
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Supersonic LTD
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # Gelf2Kafka
2
+
3
+ Runs gelfd daemon that accepts gelf events and pushes them to kafka.
4
+
5
+ ## Installation
6
+
7
+ Install libsnappy dev libs if you want to take advantage of compression
8
+
9
+ apt-get install libsnappy-dev
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'gelf2kafka'
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install gelf2kafka
22
+
23
+ ## Usage
24
+
25
+ $ gelf2kafka -h
26
+ Usage: gelf2kafka [options]
27
+ --config PATH Path to settings config
28
+ -h, --help Display this screen
29
+ $
30
+
31
+ ## Config
32
+
33
+ gelfd:
34
+ host: localhost
35
+ port: 11211
36
+ flush_interval: 1
37
+ max_batch_events: 1024
38
+ kafka:
39
+ brokers: ["broker1:9092", "broker2:9092", "broker3:9092"]
40
+ producer_type: sync
41
+ produce: true
42
+
43
+ ## Contributing
44
+
45
+ 1. Fork it
46
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
47
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
48
+ 4. Push to the branch (`git push origin my-new-feature`)
49
+ 5. Create new Pull Request
50
+ 6. Go to 1
data/bin/gelf2kafka ADDED
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'gelfd'
5
+ require 'poseidon'
6
+ require 'yaml'
7
+ require 'hash_symbolizer'
8
+ require 'schash'
9
+ require 'socket'
10
+ require 'timers'
11
+ require 'logger'
12
+
13
+ $stdout.sync = true
14
+
15
+ Thread.abort_on_exception = true
16
+
17
+ @config = nil
18
+
19
+ loglevels = {
20
+ :debug => Logger::DEBUG,
21
+ :info => Logger::INFO,
22
+ :warn => Logger::WARN,
23
+ :error => Logger::Error,
24
+ :fatal => Logger::FATAL,
25
+ :unknown => Logger::UNKNOWN
26
+ }
27
+
28
+ @loglevel = Logger::INFO
29
+
30
+ opts = OptionParser.new
31
+ opts.banner = "Usage: #{$0} [options]"
32
+ opts.on( '--config PATH', String, 'Path to settings config' ) { |c| @config = c }
33
+ opts.on( '--log-level [LEVEL]', [:debug, :info, :warn, :error, :fatal, :unknown] ) { |l| @loglevel = loglevels[l] }
34
+ opts.on( '-h', '--help', 'Display this screen' ) { puts opts; exit 0 }
35
+ opts.parse!
36
+
37
+ unless @config
38
+ puts opts
39
+ exit 1
40
+ end
41
+
42
+ @logger = Logger.new(STDOUT)
43
+
44
+ @settings = YAML.load_file(@config).symbolize_keys(true)
45
+
46
+ validator = Schash::Validator.new do
47
+ {
48
+ gelfd: {
49
+ host: string,
50
+ port: integer,
51
+ flush_interval: integer,
52
+ max_batch_events: integer
53
+ },
54
+ kafka: {
55
+ brokers: array_of(string),
56
+ producer_type: match(/^(sync|async)$/),
57
+ produce: optional(boolean),
58
+ topic: string
59
+ },
60
+ }
61
+ end
62
+
63
+ unless validator.validate(@settings).empty?
64
+ @logger.error("ERROR: bad settings")
65
+ @logger.error(validator.validate(@settings))
66
+ exit 1
67
+ end
68
+
69
+ @gelfd_host = @settings[:gelfd][:host]
70
+ @gelfd_port = @settings[:gelfd][:port]
71
+ @flush_interval = @settings[:gelfd][:flush_interval]
72
+ @max_batch_events = @settings[:gelfd][:max_batch_events]
73
+ @brokers = @settings[:kafka][:brokers]
74
+ @producer_type = @settings[:kafka][:producer_type].to_sym
75
+ @produce = @settings[:kafka].has_key?(:produce) ? @settings[:kafka][:produce] : true
76
+ @topic = @settings[:kafka][:topic]
77
+ @producer = Poseidon::Producer.new(@brokers, "#{Socket.gethostname}", :type => @producer_type, :compression_codec => :snappy, :compressed_topics => [ @topic ]) if @produce
78
+
79
+ @mutex = Mutex.new
80
+
81
+ @producer_queue = SizedQueue.new(10)
82
+
83
+ @producer_thread = Thread.new do
84
+ loop do
85
+ messages = @producer_queue.pop
86
+ begin
87
+ @producer.send_messages(messages) if @produce
88
+ rescue Poseidon::Errors::UnableToFetchMetadata
89
+ @logger.warn("Got Poseidon::Errors::UnableToFetchMetadata while trying to produce kafka messages, retrying in 1 second ...")
90
+ sleep 1
91
+ retry
92
+ end
93
+ end
94
+ end
95
+
96
+ @timers = Timers::Group.new
97
+ @flush_timer = @timers.every(@flush_interval) do
98
+ @logger.debug("Flush timer triggered with #{@messages.size} events")
99
+ @mutex.synchronize do
100
+ @producer_queue.push(@messages) unless @messages.empty?
101
+ @messages = []
102
+ end
103
+ end
104
+ Thread.new { loop { @timers.wait } }
105
+
106
+ def gelfd
107
+ server = UDPSocket.new
108
+ @logger.info("binding gelfd to #{@gelfd_host}:#{@gelfd_port}")
109
+ server.bind(@gelfd_host, @gelfd_port)
110
+
111
+ @messages = []
112
+
113
+ loop do
114
+ data, addr = server.recvfrom(8192)
115
+ begin
116
+ res = Gelfd::Parser.parse(data)
117
+ unless res.nil?
118
+ @mutex.synchronize do
119
+ @messages << Poseidon::MessageToSend.new(@topic, res.strip)
120
+ if @messages.size >= @max_batch_events
121
+ @logger.debug("Max events threshold reached")
122
+ @producer_queue.push(@messages)
123
+ @messages = []
124
+ end
125
+ end
126
+ end
127
+ rescue Exception => e
128
+ @logger.warn("Failed parsing gelf message: #{e.message}")
129
+ end
130
+ end
131
+ end
132
+
133
+ gelfd
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path('../lib/', __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require "gelf2kafka/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "gelf2kafka"
8
+ s.version = Gelf2Kafka::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Alexander Piavlo"]
11
+ s.email = ["devops@supersonic.com"]
12
+ s.homepage = "http://github.com/SupersonicAds/gelf2kafka"
13
+ s.summary = "Gelf deamon what sends events to kafka"
14
+ s.description = "Gelf deamon what sends events to kafka"
15
+ s.license = 'MIT'
16
+ s.has_rdoc = false
17
+
18
+ s.add_dependency('gelfd')
19
+ s.add_dependency('poseidon')
20
+ s.add_dependency('snappy')
21
+ s.add_dependency('hash_symbolizer')
22
+ s.add_dependency('schash')
23
+ s.add_dependency('timers')
24
+
25
+ s.add_development_dependency('rake')
26
+
27
+ s.files = Dir.glob("{bin,lib}/**/*") + %w(gelf2kafka.gemspec LICENSE README.md)
28
+ s.executables = Dir.glob('bin/**/*').map { |file| File.basename(file) }
29
+ s.test_files = nil
30
+ s.require_paths = ['lib']
31
+ end
@@ -0,0 +1,3 @@
1
+ module Gelf2Kafka
2
+ VERSION ||= '0.1.0'
3
+ end
data/lib/gelf2kafka.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Gelf2Kafka
2
+ require 'gelf2kafka/version.rb'
3
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gelf2kafka
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Piavlo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gelfd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: poseidon
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: snappy
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: hash_symbolizer
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: schash
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: timers
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Gelf deamon what sends events to kafka
112
+ email:
113
+ - devops@supersonic.com
114
+ executables:
115
+ - gelf2kafka
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - LICENSE
120
+ - README.md
121
+ - bin/gelf2kafka
122
+ - gelf2kafka.gemspec
123
+ - lib/gelf2kafka.rb
124
+ - lib/gelf2kafka/version.rb
125
+ homepage: http://github.com/SupersonicAds/gelf2kafka
126
+ licenses:
127
+ - MIT
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.2.2
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: Gelf deamon what sends events to kafka
149
+ test_files: []