gelfd 0.0.1
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.
- 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
|
+
|