gelfd 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +6 -0
- data/Rakefile +1 -0
- data/bin/gelfd +19 -0
- data/gelfd.gemspec +24 -0
- data/lib/gelfd.rb +16 -0
- data/lib/gelfd/chunked_parser.rb +46 -0
- data/lib/gelfd/exceptions.rb +8 -0
- data/lib/gelfd/gzip_parser.rb +9 -0
- data/lib/gelfd/parser.rb +21 -0
- data/lib/gelfd/version.rb +3 -0
- data/lib/gelfd/zlib_parser.rb +15 -0
- data/test/fixtures/unchunked.zl +0 -0
- metadata +68 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
# gelfd
|
2
|
+
gelfd is a standalone implementation of GELF (Graylog2 Extended Log Format).
|
3
|
+
This is used by the graylog2 server as an extended format for handling log messages.
|
4
|
+
|
5
|
+
## Rationale
|
6
|
+
This was originally concieved as a way to provide a graylog2-compatible input for logstash.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/gelfd
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
3
|
+
require 'socket'
|
4
|
+
require 'gelfd'
|
5
|
+
|
6
|
+
server = UDPSocket.new
|
7
|
+
puts "Starting up"
|
8
|
+
server.bind(nil, 11211)
|
9
|
+
trap("INT") { puts "Shutting down"; exit }
|
10
|
+
|
11
|
+
loop do
|
12
|
+
data, addr = server.recvfrom(8192)
|
13
|
+
begin
|
14
|
+
res = Gelfd::Parser.parse(data)
|
15
|
+
rescue Exception => e
|
16
|
+
puts e.message
|
17
|
+
end
|
18
|
+
puts res unless res.nil?
|
19
|
+
end
|
data/gelfd.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "gelfd/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "gelfd"
|
7
|
+
s.version = Gelfd::VERSION
|
8
|
+
s.authors = ["John E. Vincent"]
|
9
|
+
s.email = ["lusis.org+github.com@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Pure ruby gelf server and decoding library}
|
12
|
+
s.description = %q{Standalone implementation of the Graylog Extended Log Format}
|
13
|
+
|
14
|
+
s.rubyforge_project = "gelfd"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
data/lib/gelfd.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "gelfd/version"
|
2
|
+
|
3
|
+
module Gelfd
|
4
|
+
CHUNKED_MAGIC = [0x1e,0x0f].pack('C*').freeze
|
5
|
+
ZLIB_MAGIC = [0x78,0x9c].pack('C*').freeze
|
6
|
+
GZIP_MAGIC = [0x1f,0x8b].pack('C*').freeze
|
7
|
+
HEADER_LENGTH = 12
|
8
|
+
DATA_LENGTH = 8192 - HEADER_LENGTH
|
9
|
+
MAX_CHUNKS = 128
|
10
|
+
end
|
11
|
+
|
12
|
+
require File.join(File.dirname(__FILE__), 'gelfd', 'exceptions')
|
13
|
+
require File.join(File.dirname(__FILE__), 'gelfd', 'zlib_parser')
|
14
|
+
require File.join(File.dirname(__FILE__), 'gelfd', 'gzip_parser')
|
15
|
+
require File.join(File.dirname(__FILE__), 'gelfd', 'chunked_parser')
|
16
|
+
require File.join(File.dirname(__FILE__), 'gelfd', 'parser')
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Gelfd
|
2
|
+
class ChunkedParser
|
3
|
+
@@chunk_map = Hash.new {|hash,key| hash[key] = {:total_chunks => 0, :chunks => {} } }
|
4
|
+
|
5
|
+
attr_accessor :message_id, :max_chunks, :decoded_data, :chunks, :seen
|
6
|
+
|
7
|
+
def self.parse(data)
|
8
|
+
msg_id = self.parse_chunk(data)
|
9
|
+
if @@chunk_map[msg_id][:chunks].size == @@chunk_map[msg_id][:total_chunks]
|
10
|
+
assemble_chunks(msg_id)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.assemble_chunks(msg_id)
|
15
|
+
buff = ''
|
16
|
+
chunks = @@chunk_map[msg_id][:chunks]
|
17
|
+
chunks.keys.sort.each do |k|
|
18
|
+
buff += chunks[k]
|
19
|
+
end
|
20
|
+
begin
|
21
|
+
# TODO
|
22
|
+
# This has a chance for an DoS
|
23
|
+
# you can send a chunked message as a chunked message
|
24
|
+
t = Parser.parse(buff.clone)
|
25
|
+
t
|
26
|
+
rescue Exception => e
|
27
|
+
"Exception: #{e.message}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def self.parse_chunk(data)
|
33
|
+
header = data[0..1]
|
34
|
+
raise NotChunkedDataError, "This doesn't look like a Chunked GELF message!" if header != CHUNKED_MAGIC
|
35
|
+
begin
|
36
|
+
msg_id = data[2..9].unpack('C*').join
|
37
|
+
seq_number, total_number = data[10].ord, data[11].ord
|
38
|
+
zlib_chunk = data[12..-1]
|
39
|
+
raise TooManyChunksError, "#{total_number} greater than #{MAX_CHUNKS}" if total_number > MAX_CHUNKS
|
40
|
+
@@chunk_map[msg_id][:total_chunks] = total_number.to_i
|
41
|
+
@@chunk_map[msg_id][:chunks].merge!({seq_number.to_i => zlib_chunk})
|
42
|
+
msg_id
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Gelfd
|
2
|
+
class NotChunkedDataError < StandardError; end
|
3
|
+
class DuplicateChunkError < StandardError; end
|
4
|
+
class TooManyChunksError < StandardError; end
|
5
|
+
class UnknownHeaderError < StandardError; end
|
6
|
+
class DecodeError < StandardError; end
|
7
|
+
class NotYetImplementedError < StandardError; end
|
8
|
+
end
|
data/lib/gelfd/parser.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gelfd
|
2
|
+
class Parser
|
3
|
+
|
4
|
+
def self.parse(data)
|
5
|
+
header = data[0..1]
|
6
|
+
case header
|
7
|
+
when ZLIB_MAGIC
|
8
|
+
ZlibParser.parse(data)
|
9
|
+
when CHUNKED_MAGIC
|
10
|
+
ChunkedParser.parse(data)
|
11
|
+
when GZIP_MAGIC
|
12
|
+
GzipParser.parse(data)
|
13
|
+
else
|
14
|
+
raise UnknownHeaderError, "Could not find parser for header: #{header.unpack('C*').to_s}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gelfd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- John E. Vincent
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-09-09 00:00:00 Z
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Standalone implementation of the Graylog Extended Log Format
|
17
|
+
email:
|
18
|
+
- lusis.org+github.com@gmail.com
|
19
|
+
executables:
|
20
|
+
- gelfd
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files: []
|
24
|
+
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- Gemfile
|
28
|
+
- README.md
|
29
|
+
- Rakefile
|
30
|
+
- bin/gelfd
|
31
|
+
- gelfd.gemspec
|
32
|
+
- lib/gelfd.rb
|
33
|
+
- lib/gelfd/chunked_parser.rb
|
34
|
+
- lib/gelfd/exceptions.rb
|
35
|
+
- lib/gelfd/gzip_parser.rb
|
36
|
+
- lib/gelfd/parser.rb
|
37
|
+
- lib/gelfd/version.rb
|
38
|
+
- lib/gelfd/zlib_parser.rb
|
39
|
+
- test/fixtures/unchunked.zl
|
40
|
+
homepage: ""
|
41
|
+
licenses: []
|
42
|
+
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project: gelfd
|
63
|
+
rubygems_version: 1.8.6
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Pure ruby gelf server and decoding library
|
67
|
+
test_files: []
|
68
|
+
|