gelf2kafka 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []