em-syslog-logger 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/lib/em-syslog.rb +224 -0
- metadata +76 -0
data/lib/em-syslog.rb
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
|
2
|
+
require 'socket'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'eventmachine'
|
5
|
+
|
6
|
+
module EventMachine
|
7
|
+
module Syslog
|
8
|
+
# THIEVERY: http://github.com/kpumuk/ruby_syslog
|
9
|
+
SEVERITIES = {
|
10
|
+
:emergency => 0, # system is unusable
|
11
|
+
:alert => 1, # action must be taken immediately
|
12
|
+
:critical => 2, # critical conditions
|
13
|
+
:error => 3, # error conditions
|
14
|
+
:warning => 4, # warning conditions
|
15
|
+
:notice => 5, # normal but significant condition
|
16
|
+
:informational => 6, # informational messages
|
17
|
+
:info => 6, # informational messages (short name for the previous)
|
18
|
+
:debug => 7 # debug-level messages
|
19
|
+
}
|
20
|
+
# THIEVERY: http://github.com/kpumuk/ruby_syslog
|
21
|
+
FACILITIES = {
|
22
|
+
:kernel => 0, # kernel messages
|
23
|
+
:user_level => 1, # user-level messages
|
24
|
+
:mail => 2, # mail system
|
25
|
+
:daemons => 3, # system daemons
|
26
|
+
:security => 4, # security/authorization messages
|
27
|
+
:internal => 5, # messages generated internally by syslogd
|
28
|
+
:printer => 6, # line printer subsystem
|
29
|
+
:network => 7, # network news subsystem
|
30
|
+
:uucp => 8, # UUCP subsystem
|
31
|
+
:clock => 9, # clock daemon
|
32
|
+
:security1 => 10, # security/authorization messages
|
33
|
+
:ftp => 11, # FTP daemon
|
34
|
+
:ntp => 12, # NTP subsystem
|
35
|
+
:log_audit => 13, # log audit
|
36
|
+
:log_alert => 14, # log alert
|
37
|
+
:clock1 => 15, # clock daemon
|
38
|
+
:local0 => 16, # local use 0
|
39
|
+
:local1 => 17, # local use 1
|
40
|
+
:local2 => 18, # local use 2
|
41
|
+
:local3 => 19, # local use 3
|
42
|
+
:local4 => 20, # local use 4
|
43
|
+
:local5 => 21, # local use 5
|
44
|
+
:local6 => 22, # local use 6
|
45
|
+
:local7 => 23 # local use 7
|
46
|
+
}
|
47
|
+
|
48
|
+
def self.logger( *a)
|
49
|
+
EventMachine::Logger.new( *a)
|
50
|
+
end
|
51
|
+
|
52
|
+
module ConnectionUDP
|
53
|
+
# EM does not support doing UDP over unix domain sockets, so we have to manually handle it.
|
54
|
+
def self.create_unix
|
55
|
+
::Socket.new(
|
56
|
+
::Socket::PF_UNIX,
|
57
|
+
::Socket::SOCK_DGRAM
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.pack_unix( path)
|
62
|
+
::Socket.pack_sockaddr_un( path)
|
63
|
+
end
|
64
|
+
|
65
|
+
def setup( host, port, unix_connection=nil)
|
66
|
+
@host = unix_connection.nil? ? host : ::Socket.pack_sockaddr_un( host)
|
67
|
+
@port = port
|
68
|
+
@unix_connection = unix_connection
|
69
|
+
@unix_connection.connect( @host) unless @unix_connection.nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
# Should not be needed
|
73
|
+
def notify_readable
|
74
|
+
read_packet
|
75
|
+
end
|
76
|
+
|
77
|
+
def read_packet
|
78
|
+
data, sender = @unix_connection.recvfrom( 1024)
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
def send_msg( msg)
|
83
|
+
if @unix_connection.nil?
|
84
|
+
send_datagram( msg, @host, @port)
|
85
|
+
else
|
86
|
+
@unix_connection.send( msg, 0)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module ConnectionTCP
|
92
|
+
def setup( host, port)
|
93
|
+
@host = host
|
94
|
+
@port = port
|
95
|
+
@queue = Array.new
|
96
|
+
@connected = false
|
97
|
+
end
|
98
|
+
|
99
|
+
def post_init
|
100
|
+
@connected = true
|
101
|
+
@queue.size.times {
|
102
|
+
send_msg( @queue.shift)
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def send_msg( msg)
|
107
|
+
if @connected
|
108
|
+
send_data( msg)
|
109
|
+
else
|
110
|
+
@queue.push( msg)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def unbind
|
115
|
+
@connected = false
|
116
|
+
reconnect( @host, @port)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class Logger
|
122
|
+
@@connection_cache = Hash.new
|
123
|
+
attr_reader :idenity, :resource
|
124
|
+
|
125
|
+
# Yup hack new class method for cache candy
|
126
|
+
def self.new( idenity, resource="unix://dev/log")
|
127
|
+
# See if we have a connection already in our cache
|
128
|
+
key = self.mk_cache_index_key( idenity, resource)
|
129
|
+
return @@connection_cache[key] if @@connection_cache.has_key? key and @@connection_cache[key].error? == false
|
130
|
+
|
131
|
+
# Otherwise allocate a new object to do the work
|
132
|
+
instance = self.allocate
|
133
|
+
instance.send( :initialize, idenity, resource)
|
134
|
+
@@connection_cache[key] = instance
|
135
|
+
end
|
136
|
+
|
137
|
+
def initialize( idenity, resource)
|
138
|
+
@idenity = idenity.to_s + "[" + Process.pid.to_s + "]"
|
139
|
+
@resource = resource
|
140
|
+
resource = self.class.parse_resource( resource)
|
141
|
+
|
142
|
+
case resource[0]
|
143
|
+
when :unix
|
144
|
+
# need better checking here
|
145
|
+
raise "unix domain socket #{resource[1]} does not exist!" unless ::File.exists?( resource[1])
|
146
|
+
@connection = Syslog::ConnectionUDP.create_unix
|
147
|
+
resource << @connection
|
148
|
+
@connection = EM.watch( @connection, Syslog::ConnectionUDP)
|
149
|
+
when :tcp
|
150
|
+
@connection = EM.connect( resource[1], resource[2], Syslog::ConnectionTCP)
|
151
|
+
else
|
152
|
+
@connection = EM.open_datagram_socket( '0.0.0.0', 0, Syslog::ConnectionUDP)
|
153
|
+
end
|
154
|
+
raise "unable to create connection" if @connection.nil?
|
155
|
+
resource.shift
|
156
|
+
@connection.setup( *resource)
|
157
|
+
end
|
158
|
+
|
159
|
+
def log( msg, facility, severity, debug=true)
|
160
|
+
m = String.new
|
161
|
+
if debug
|
162
|
+
raise "Invalid log severity!" unless Syslog::SEVERITIES.has_key? severity
|
163
|
+
raise "Invalid log facility!" unless Syslog::FACILITIES.has_key? facility
|
164
|
+
end
|
165
|
+
m += "<" + self.class.class_variable_get("@@syskey_#{facility}_#{severity}".to_sym).to_s + ">"
|
166
|
+
m += self.class.timestamp + " " + ::Socket.gethostname + " #{@idenity} " + msg.to_s
|
167
|
+
@connection.send_msg( m)
|
168
|
+
end
|
169
|
+
|
170
|
+
#Meta program our facility/severity keys and methods
|
171
|
+
Syslog::FACILITIES.each {|facility,facility_int|
|
172
|
+
Syslog::SEVERITIES.each {|severity,severity_int|
|
173
|
+
define_method( "#{facility}_#{severity}".to_sym) do |msg|
|
174
|
+
log( msg, facility, severity, false)
|
175
|
+
end
|
176
|
+
self.class_variable_set("@@syskey_#{facility}_#{severity}".to_sym, (facility_int * 8 + severity_int))
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
private
|
181
|
+
def self.timestamp( time=Time.now)
|
182
|
+
day = time.strftime("%d")
|
183
|
+
day = day.sub(/^0/, ' ') if day =~ /^0\d/
|
184
|
+
time.strftime("%b #{day} %H:%M:%S")
|
185
|
+
end
|
186
|
+
|
187
|
+
# Likely not the fastest and best way to make a cache index
|
188
|
+
def self.mk_cache_index_key( idenity, resource)
|
189
|
+
idenity.to_s + resource.split(':').each {|i| i.gsub(/\./,'') }.join
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.parse_resource( resource)
|
193
|
+
split_point = resource.index(':')
|
194
|
+
answer = [ resource[0..(split_point-1)].to_sym, resource[(split_point+1)..-1]]
|
195
|
+
split_point = answer[1].index(':')
|
196
|
+
if split_point.nil? == false and split_point > 0
|
197
|
+
answer << answer[1][(split_point+1)..-1].to_i
|
198
|
+
answer[1] = answer[1][0..(split_point-1)]
|
199
|
+
elsif split_point.nil? and answer[0] != :unix
|
200
|
+
answer << 514
|
201
|
+
elsif split_point.nil? == false
|
202
|
+
raise "Resource parse error"
|
203
|
+
else
|
204
|
+
answer[1].slice!(0)
|
205
|
+
answer << nil
|
206
|
+
end
|
207
|
+
answer
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
if __FILE__ == $0
|
213
|
+
EM.run {
|
214
|
+
EM.kqueue if EM.kqueue?
|
215
|
+
EM.epoll if EM.epoll?
|
216
|
+
|
217
|
+
logger = EM::Syslog.logger( "em-syslog-test")
|
218
|
+
EM.next_tick {
|
219
|
+
logger.log( "TEST INFO", :daemons, :info)
|
220
|
+
logger.mail_error( "MAIL ERROR")
|
221
|
+
}
|
222
|
+
}
|
223
|
+
end
|
224
|
+
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: em-syslog-logger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Digital Akasha
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2012-12-12 00:00:00 -06:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: eventmachine
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 12
|
30
|
+
- 10
|
31
|
+
version: 0.12.10
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description:
|
35
|
+
email: tormenta@digitalakasha.com
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- lib/em-syslog.rb
|
44
|
+
has_rdoc: true
|
45
|
+
homepage: https://github.com/tormenta/em-syslog
|
46
|
+
licenses: []
|
47
|
+
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.3.6
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Simple Logger Class For Eventmachine Applications
|
75
|
+
test_files: []
|
76
|
+
|