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.
Files changed (2) hide show
  1. data/lib/em-syslog.rb +224 -0
  2. 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
+