Compare commits

...

11 Commits

Author SHA1 Message Date
Denis Knauf c919500ae3 README: gems removed (automaticaly installed) 2011-06-08 23:03:42 +02:00
Denis Knauf 1063201b64 README: tc 2011-06-08 22:59:25 +02:00
Denis Knauf 3bdd2e6ceb file-queue 2011-06-08 22:51:40 +02:00
Denis Knauf 1efdf76ffc s2l -> s2l | rotate | bdb 2011-05-07 00:54:56 +02:00
Denis Knauf 896f641856 s2l: use logger 2011-03-19 09:59:06 +01:00
Denis Knauf 507951114e little changes: metafiles 2010-03-20 23:28:09 +01:00
Denis Knauf 27f2157bf8 more readme 2010-03-17 13:27:28 +01:00
Denis Knauf 3cc2e489b5 gemcutter-ready. memory-based-transactions. (100x faster, but no transactionlogs!) 2010-03-11 00:34:01 +01:00
Denis Knauf 34bb509b92 New dep: robustserver. BDB::Env will reopen on error. Version 0.0.2 2010-03-02 14:10:58 +01:00
Denis Knauf 1989ade585 Uses new SBDB-API 2010-02-26 14:08:03 +01:00
Denis Knauf 36aecb7197 Log-Queue: first try 2010-02-22 16:20:35 +01:00
14 changed files with 431 additions and 210 deletions

View File

View File

@ -1,58 +1,48 @@
Dependencies
============
incomplete yet.
System
------
* ruby >= 1.9 (tested: 1.9.1, untested: 1.8 (maybe compatible))
* libdb >= 4 (tested: 4.7)
* C-Compiler
* tokyocabinet
### Debian/Ubuntu:
# aptitude ruby1.9.1 ruby1.9.1-dev libdb4.7-dev rubygems1.9.1
# aptitude ruby1.9.1 ruby1.9.1-dev rubygems1.9.1 libtokyocabinet-dev libtokyotyrant-dev
If you've installed ruby1.8 (yet), you should run ruby1.9.1 instead ruby and
If you've installed ruby1.8 (yet), you should run ruby1.9.1 instead ruby and
gem1.9.1 instead gem.
Change shebash in s2l.rb to
#!/usr/bin/ruby1.9.1
or
Ruby Gems
---------
* BDB >= 0.2.2 (patch needed - gem included)
* UUIDTools
Install: (in syslog2logan-dir)
# gem install bdb-0.2.2.gem uuidtools
#!/usr/bin/env ruby1.9.1
Install
=======
# gem build syslog2logan.gemspec
# gem install syslog2logan-*.gem
# gem install syslog2logan
Usage
=====
First you should know, the database environments are in *this* directory,
where you call *s2l.rb*. You must use this directory for logan itself too!
Don't use this directory for anything else.
Start
-----
Simple:
Simple on Ubuntu:
# ./s2l.rb
# /var/lib/gems/1.9*/gems/syslog2logan-*/bin/s2l.rb
Or deamonized:
# sh -c 'nohup ./s2l.rb </dev/null >/dev/null 2>&1 &' &
Deamonized:
# sh -c 'nohup PATHTO/s2l.rb </dev/null >/dev/null 2>&1 &' &
Use it
------
@ -67,7 +57,7 @@ You need these lines:
source s_server {
unix-stream( "/dev/log" max-connections(100));
# internal(); # Statistics about dests. You've any other dest than the server?
# internal(); # Statistics about dests. It's unimportant for LogAn.
file( "/proc/kmsg");
};
@ -80,9 +70,6 @@ You need these lines:
destination( d_server);
};
You should use your default source.
### rsyslog
I don't know. Please tell me, if you can.
I don't know. Please tell me, how to use.

View File

@ -10,9 +10,10 @@ begin
gem.email = "Denis.Knauf@gmail.com"
gem.homepage = "http://github.com/DenisKnauf/syslog2logan"
gem.authors = ["Denis Knauf"]
gem.files = ["README.md", "VERSION", "bin/**/*", "lib/**/*.rb", "test/**/*.rb"]
gem.require_paths = ["bin"]
gem.files = %w[AUTHORS README.md VERSION bin/**/* lib/**/*.rb test/**/*.rb]
gem.require_paths = %w[bin]
gem.add_dependency 'sbdb'
gem.add_dependency 'robustserver'
gem.add_dependency 'select'
end
Jeweler::GemcutterTasks.new

View File

@ -1 +1 @@
0.0.1
0.0.3.0

View File

@ -1,152 +1,58 @@
#!/usr/bin/ruby
$:.push File.join( File.dirname( $0), '..', 'lib')
require 'logger'
require 'json'
require 'rubygems'
require 'sbdb'
require 'uuidtools'
require 'socket'
require 'select'
require 'robustserver'
require 'active_support'
require 'syslog2logan/rotate'
require 'syslog2logan/server'
class S2L < Select::Server
def init p
super p
@dbs = p[:dbs]
end
def event_new_client a
{ :clientclass => S2L::Socket, :dbs => @dbs }
end
end
$logger = Logger.new $stderr
$logger.formatter = proc { |severity, datetime, progname, msg| [severity, datetime, progname, msg.inspect].to_json+"\n" }
module Kernel
def debug( *p) logger :debug, *p end
def info( *p) logger :info, *p end
def warn( *p) logger :warn, *p end
def error( *p) logger :error, *p end
def fatal( *p) logger :fatal, *p end
def logger l, *p
p = p.first if p.length == 1
$stderr.puts [Time.now, l, p].inspect
end
private :logger
def logger() $logger end
end
class S2L::Socket < Select::Socket
def init opts
@dbs = opts[ :dbs]
super opts
class Main < RobustServer
def initialize conf
super
@logger = $logger
@conf = conf
logger.info :open => S2L
@serv = S2L.new :sock => TCPServer.new( *@conf[:server])
@sigs[:INT] = @sigs[:TERM] = method(:shutdown)
@sigs[:USR1] = method(:state)
end
def event_line v
@dbs.emit v
end
alias emit event_line
end
class Rotate
def initialize db, &e
@rdb, @env, @dbs = db, db.home, {}
self.hash = e || lambda {|k|
[UUIDTools::UUID.parse_raw( k).timestamp.to_i/60/60/24].pack 'N'
}
def state s = nil
logger.debug :server => @serv.class
end
def hash= e
self.hash &e
def shutdown s = nil
logger.info :shutdown => [s, Signal[s]]
@serv.close
exit 0
end
def hash &e
@hash_func = e if e
@hash_func
end
def hashing k
@hash_func.call k
end
def db k
n = @rdb[ h]
if n
n = UUIDTools::UUID.parse_raw n
else
n = UUIDTools::UUID.timestamp_create
@rdb[ h] = n.raw
end
info :open => n.to_s
@env[ n.to_s, 'logs', SBDB::Btree, SBDB::CREATE | SBDB::AUTO_COMMIT]
@env[ "#{n}.newids", 'logs', SBDB::Queue, SBDB::CREATE | SBDB::AUTO_COMMIT]
end
def sync
@dbs.each{|n,db|db.sync}
@rdb.sync
end
def close
@dbs.each{|n,db|db.close 0}
@rdb.close 0
end
def put v
id = UUIDTools::UUID.timestamp_create
s = [0x10, v].pack 'Na*'
db(id.raw)[ id.raw] = s
end
alias emit put
end
class Retries
attr_accessor :max, :range
attr_reader :count, :last
def initialize max = 10, range = 10
@max, @range, @count, @last = max, range, 0, Time.now
end
def retry?
@count = @last + @range > Time.now ? @count + 1 : 1
@last = Time.now
@count < @max
end
def run ex, &e
begin e.call *args
rescue ex
retries.retry? and retry
def run
logger.info :open => @conf[:backend]
@conf[:backend][0].new( @conf[:backend][1]) do |backend|
logger.info :open => Rotate
@serv.dbs = Rotate.new &backend.to_proc
logger.info :run => @serv.class
@serv.run
logger.info :close => @conf[:backend]
end
end
end
$conf = {
:home => 'logs',
:server => [ '', 1514],
:retries => [10, 10]
}
require 'syslog2logan/backend/tch'
Main.main :backend => [ Backend::TCH, {:dir => 'logs'}], :server => [ '', 1514], :retries => [1,1] # [10, 10]
info :create => {:home => $conf[:home]}
Dir.mkdir $conf[:home] rescue Errno::EEXIST
info :open => SBDB::Env
SBDB::Env.new( $conf[:home], SBDB::CREATE | SBDB::Env::INIT_TRANSACTION | Bdb::DB_AUTO_COMMIT) do |dbenv|
info :open => Rotate
dbs = Rotate.new dbenv[ 'rotates.db', 'rotates', SBDB::Btree, SBDB::CREATE | Bdb::DB_AUTO_COMMIT]
info :open => S2L
serv = S2L.new :sock => TCPServer.new( *$conf[:server]), :dbs => dbs
retries = Retries.new *$conf[:retries]
begin
info :run => serv
serv.run
info :shutdown => :stoped
rescue Interrupt
info :shutdown => :interrupted
rescue SignalException
info :shutdown => :signal
rescue Object
error :exception=>$!, :backtrace=>$!.backtrace
retries.retry? and retry
fatal "Too many retries (#{retries.count})"
info :shutdown => :fatal
end
info :close => dbenv
end
info :halted
logger.info :halted

48
lib/file_queue.rb Normal file
View File

@ -0,0 +1,48 @@
class File
def exclusive_lock
flock File::LOCK_EX
end
def shared_lock
flock File::LOCK_SH
end
def unblock
flock File::LOCK_UN
end
end
class FileQueue
attr_reader :file, :size
alias to_io file
def initialize file, size = 16
@file = case file
when File then file
else File.open file, 'a+'
end
@size, @pack = size, "A#{size}"
end
def push *a
f = @file
f.seek 0, IO::SEEK_END
f.exclusive_lock
f.write a.pack( @pack*a.length)
f.unblock
end
def pop
f = @file
f.rewind
f.exclusive_lock
s = f.read( @size).unpack( 'L')[0]
f.rewind
f.write [s.succ].pack( 'L')
f.sync
f.shared_lock
f.pos = s
f.read( @size).unpack( 'L')[0]
f.unblock
end
end

83
lib/in_tch.rb Normal file
View File

@ -0,0 +1,83 @@
#!/usr/bin/ruby
require 'logger'
require 'rubygems'
require 'uuidtools'
require 'socket'
require 'select'
require 'robustserver'
require 'active_support'
require 'syslog2logan/rotate'
$logger = Logger.new $stderr
class S2L < Select::Server
attr_accessor :dbs
def init p
super p
@dbs = p[:dbs]
end
def event_new_client a
logger.debug :connection => {:new => a}
{ :clientclass => S2L::Socket, :dbs => @dbs }
end
end
module Kernel
def logger() $logger end
end
class S2L::Socket < Select::Socket
def init opts
@dbs = opts[ :dbs]
super opts
end
def event_line v
logger.debug :line => v
@dbs.emit v
end
alias emit event_line
end
class Main < RobustServer
def initialize conf
super
@logger = $logger
@conf = conf
logger.info :open => S2L
@serv = S2L.new :sock => TCPServer.new( *@conf[:server])
logger.info :create => {:home => @conf[:home]}
Dir.mkdir @conf[:home] rescue Errno::EEXIST
@sigs[:INT] = @sigs[:TERM] = method(:shutdown)
@sigs[:USR1] = method(:state)
end
def state s = nil
logger.debug :server => @serv
end
def shutdown s = nil
logger.info :shutdown => [s, Signal[s]]
@serv.close
exit 0
end
def run
logger.info :open => SBDB::Env
SBDB::Env.new( @conf[:home],
log_config: SBDB::Env::LOG_IN_MEMORY | SBDB::Env::LOG_AUTO_REMOVE,
flags: SBDB::CREATE | SBDB::Env::INIT_TXN | Bdb::DB_INIT_MPOOL) do |dbenv|
logger.info :open => Rotate
@serv.dbs = Rotate.new dbenv[ 'rotates.db', :type => SBDB::Btree, :flags => SBDB::CREATE | Bdb::DB_AUTO_COMMIT]
logger.info :run => @serv
@serv.run
end
end
end
Main.main :home => 'logs', :server => [ '', 1514], :retries => [1,1] # [10, 10]
logger.info :halted

View File

@ -0,0 +1,16 @@
module Backend
end
class Backend::Base
def initialize opts = {}
if block_given?
yield self
else
self
end
end
def to_proc
method :open
end
end

View File

@ -0,0 +1,31 @@
require 'rufus/tokyo'
require 'syslog2logan/backend/base'
class Backend::TCH < Backend::Base
attr_reader :dir
def initialize opts = {}, &e
@dir = opts[:dir]
Dir.mkdir @dir rescue Errno::EEXIST
@dbs = []
if block_given?
begin
super opts, &e
ensure
close
end
else
super opts
end
end
def close
@dbs.each &:close
end
def open name
logger.info :open => name, :backend => self.class
db = Rufus::Tokyo::Cabinet.new File.join( @dir, name)+".tch"
@dbs.push db
db
end
end

View File

@ -0,0 +1,2 @@
require 'syslog2logan/rotate/base.rb'

View File

@ -0,0 +1,58 @@
#!/usr/bin/ruby
require 'logger'
require 'uuidtools'
require 'active_support/core_ext'
class Rotate
# open_db_func: must returns a db-object with #[] and #[]=.
# #sync and #close are optional, for Rotate#sync, Rotate#close.
def initialize hash_func = nil, &open_db_func
@dbs = Hash.new {|h,k| h[k] = open_db_func.call(k) }
hash_func ||= lambda {|k| [k.timestamp.to_i/1.day].pack 'N' }
define_singleton_method :hashing, &hash_func
@rotate = @dbs['rotate']
@queue = @dbs['queue']
end
def db_name id
h = hashing id
n = @rotate[ h]
if n
n = UUIDTools::UUID.parse_raw n
else
n = UUIDTools::UUID.timestamp_create
@rotate[ h] = n.raw
logger.info :create => n.to_s
end
n
end
# Synchronize data to disc.
# Only avaible if db-backend provides #sync.
def sync
@dbs.each {|n, db| db.sync }
@rotate.sync
@queue.sync
end
# Close databases.
# Only avaible if db-backend provides #close.
def close
@dbs.each {|n, db| db.close }
@rotate.close
@queue.close
end
# Put new logline to databases.
# This will be written in a database with an UUID as name.
# If this db don't exist, it will be created via open_db_func (#initialize).
def put v
id = UUIDTools::UUID.timestamp_create
s = [0x10, v].pack 'Na*'
n = db_name id
@dbs[n][ id.raw] = s
@queue.push id.raw
end
alias emit put
end

View File

@ -0,0 +1,108 @@
#!/usr/bin/ruby
require 'logger'
require 'rubygems'
require 'sbdb'
require 'uuidtools'
require 'socket'
require 'select'
require 'robustserver'
require 'active_support'
class Rotate::BDB
def initialize db, &e
@rdb, @env, @dbs = db, db.home, {}
self.hash = e || lambda {|k|
[k.timestamp.to_i/1.hour].pack 'N'
}
end
def hash= e
self.hash &e
end
def hash &e
@hash_func = e if e
@hash_func
end
def hashing k
@hash_func.call k
end
def db_name id
h = hashing id
n = @rdb[ h]
if n
n = UUIDTools::UUID.parse_raw n
else
n = UUIDTools::UUID.timestamp_create
@rdb[ h] = n.raw
logger.info :create => n.to_s
end
n
end
def db n
@env[ n.to_s, :type => SBDB::Btree, :flags => SBDB::CREATE | SBDB::AUTO_COMMIT]
end
def queue n
@env[ "newids.queue", :type => SBDB::Queue, :flags => SBDB::CREATE | SBDB::AUTO_COMMIT, :re_len => 16]
end
def sync
@dbs.each {|n, db| db.sync }
@rdb.sync
end
def close
@dbs.each {|n, db| db.close 0 }
@rdb.close 0
end
def put v
id = UUIDTools::UUID.timestamp_create
s = [0x10, v].pack 'Na*'
n = db_name id
db( n)[ id.raw] = s
queue( n).push id.raw
end
alias emit put
end
class Main < RobustServer
def initialize conf
super
@logger = $logger
@conf = conf
logger.info :open => S2L
@serv = S2L.new :sock => TCPServer.new( *@conf[:server])
logger.info :create => {:home => @conf[:home]}
Dir.mkdir @conf[:home] rescue Errno::EEXIST
@sigs[:INT] = @sigs[:TERM] = method(:shutdown)
@sigs[:USR1] = method(:state)
end
def state s = nil
logger.debug :server => @serv
end
def shutdown s = nil
logger.info :shutdown => [s, Signal[s]]
@serv.close
exit 0
end
def run
logger.info :open => SBDB::Env
SBDB::Env.new( @conf[:home],
log_config: SBDB::Env::LOG_IN_MEMORY | SBDB::Env::LOG_AUTO_REMOVE,
flags: SBDB::CREATE | SBDB::Env::INIT_TXN | Bdb::DB_INIT_MPOOL) do |dbenv|
logger.info :open => Rotate
@serv.dbs = Rotate.new dbenv[ 'rotates.db', :type => SBDB::Btree, :flags => SBDB::CREATE | Bdb::DB_AUTO_COMMIT]
logger.info :run => @serv
@serv.run
end
end
end

View File

@ -0,0 +1,29 @@
require 'socket'
require 'select'
class S2L < Select::Server
attr_accessor :dbs
def init p
super p
@dbs = p[:dbs]
end
def event_new_client a
logger.debug :connection => {:new => a}
{ :clientclass => S2L::Socket, :dbs => @dbs }
end
end
class S2L::Socket < Select::Socket
def init opts
@dbs = opts[ :dbs]
super opts
end
def event_line v
logger.debug :line => v
@dbs.emit v
end
alias emit event_line
end

View File

@ -1,48 +0,0 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = %q{syslog2logan}
s.version = "0.0.1"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Denis Knauf"]
s.date = %q{2010-02-07}
s.default_executable = %q{s2l.rb}
s.description = %q{Syslog-Server which logs to Berkeley Databases (No SyslogDaemon)}
s.email = %q{Denis.Knauf@gmail.com}
s.executables = ["s2l.rb"]
s.extra_rdoc_files = [
"LICENSE",
"README.md"
]
s.files = [
"README.md",
"VERSION",
"bin/s2l.rb"
]
s.homepage = %q{http://github.com/DenisKnauf/syslog2logan}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["bin"]
s.rubygems_version = %q{1.3.5}
s.summary = %q{Syslog-Server}
if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<sbdb>, [">= 0"])
s.add_runtime_dependency(%q<select>, [">= 0"])
else
s.add_dependency(%q<sbdb>, [">= 0"])
s.add_dependency(%q<select>, [">= 0"])
end
else
s.add_dependency(%q<sbdb>, [">= 0"])
s.add_dependency(%q<select>, [">= 0"])
end
end