Skip to content
This repository
Browse code

Move from using daemons to using servolux

  • Loading branch information...
commit e0cba282f26fb102686bc57b33202b83d05aadca 1 parent e7f8f84
Eric Lindvall authored August 10, 2012
4  bin/remote_syslog
@@ -3,8 +3,4 @@
3 3
 require 'remote_syslog'
4 4
 require 'remote_syslog/cli'
5 5
 
6  
-EM.error_handler { |e|
7  
-  puts "Unhandled Exception: #{e.class}: #{e.message}:\n\t#{e.backtrace.join("\n\t")}"
8  
-}
9  
-
10 6
 RemoteSyslog::Cli.process!(ARGV)
3  lib/remote_syslog.rb
@@ -2,6 +2,3 @@ module RemoteSyslog
2 2
  VERSION = "1.6.5"
3 3
 end
4 4
 
5  
-require 'remote_syslog/reader'
6  
-require 'remote_syslog/tls_endpoint'
7  
-require 'remote_syslog/udp_endpoint'
87  lib/remote_syslog/agent.rb
... ...
@@ -0,0 +1,87 @@
  1
+require 'eventmachine'
  2
+require 'servolux'
  3
+
  4
+require 'remote_syslog/eventmachine_reader'
  5
+require 'remote_syslog/glob_watch'
  6
+require 'remote_syslog/message_generator'
  7
+require 'remote_syslog/udp_endpoint'
  8
+require 'remote_syslog/tls_endpoint'
  9
+
  10
+module RemoteSyslog
  11
+  class Agent < Servolux::Server
  12
+    # Who should we connect to?
  13
+    attr_accessor :destination_host, :destination_port
  14
+
  15
+    # Should use TLS?
  16
+    attr_accessor :tls
  17
+
  18
+    # TLS settings
  19
+    attr_accessor :client_cert_chain, :client_private_key, :server_cert
  20
+
  21
+    # syslog defaults
  22
+    attr_accessor :facility, :severity, :hostname
  23
+
  24
+    # Other settings
  25
+    attr_accessor :strip_color, :parse_fields, :exclude_pattern
  26
+
  27
+    # Files
  28
+    attr_reader :files
  29
+
  30
+    # How often should we check for new files?
  31
+    attr_accessor :glob_check_interval
  32
+
  33
+    def initialize(options = {})
  34
+      @files = []
  35
+      @glob_check_interval = 60
  36
+      logger = options[:logger] || Logger.new(STDERR)
  37
+
  38
+      super('remote_syslog', :logger => logger, :pid_file => options[:pid_file])
  39
+    end
  40
+
  41
+    def files=(files)
  42
+      @files = [ @files, files ].flatten.compact.uniq
  43
+    end
  44
+
  45
+    def watch_file(file)
  46
+      RemoteSyslog::EventMachineReader.new(file, 
  47
+        :callback => @message_generator.method(:transmit))
  48
+    end
  49
+
  50
+    def run
  51
+      EventMachine.run do
  52
+        EM.error_handler do |e|
  53
+          logger.error "Unhandled EventMachine Exception: #{e.class}: #{e.message}:\n\t#{e.backtrace.join("\n\t")}"
  54
+        end
  55
+
  56
+        if @tls
  57
+          max_message_size = 10240
  58
+
  59
+          connection = TlsEndpoint.new(@destination_host, @destination_port,
  60
+            :client_cert_chain => @client_cert_chain,
  61
+            :client_private_key => @client_private_key,
  62
+            :server_cert => @server_cert,
  63
+            :logger => logger)
  64
+        else
  65
+          max_message_size = 1024
  66
+          connection = UdpEndpoint.new(@destination_host, @destination_port,
  67
+            :logger => logger)
  68
+        end
  69
+
  70
+        @message_generator = RemoteSyslog::MessageGenerator.new(connection, 
  71
+          :facility => @facility, :severity => @severity, 
  72
+          :strip_color => @strip_color, :hostname => @hostname, 
  73
+          :parse_fields => @parse_fields, :exclude_pattern => @exclude_pattern,
  74
+          :max_message_size => max_message_size)
  75
+
  76
+        files.each do |file|
  77
+          RemoteSyslog::GlobWatch.new(file, @glob_check_interval, 
  78
+            method(:watch_file))
  79
+        end
  80
+      end
  81
+    end
  82
+
  83
+    def before_stopping
  84
+      EM.stop
  85
+    end
  86
+  end
  87
+end
161  lib/remote_syslog/cli.rb
... ...
@@ -1,8 +1,9 @@
1 1
 require 'optparse'
2 2
 require 'yaml'
3 3
 require 'pathname'
4  
-require 'daemons'
  4
+require 'servolux'
5 5
 
  6
+require 'remote_syslog/agent'
6 7
 
7 8
 module RemoteSyslog
8 9
   class Cli
@@ -11,6 +12,15 @@ class Cli
11 12
       'rfc3339' => /^(\S+) (\S+) ([^: ]+):? (.*)$/
12 13
     }
13 14
 
  15
+    DEFAULT_PID_FILES = [
  16
+      "/var/run/remote_syslog.pid",
  17
+      "#{ENV['HOME']}/run/remote_syslog.pid",
  18
+      "#{ENV['HOME']}/tmp/remote_syslog.pid",
  19
+      "#{ENV['HOME']}/remote_syslog.pid",
  20
+      "#{ENV['TMPDIR']}/remote_syslog.pid",
  21
+      "/tmp/remote_syslog.pid"
  22
+    ]
  23
+
14 24
     def self.process!(argv)
15 25
       c = new(argv)
16 26
       c.parse
@@ -20,8 +30,6 @@ def self.process!(argv)
20 30
     def initialize(argv)
21 31
       @argv = argv
22 32
 
23  
-      @app_name = File.basename($0) || 'remote_syslog'
24  
-
25 33
       @configfile  = '/etc/log_files.yml'
26 34
       @strip_color = false
27 35
       @exclude_pattern = nil
@@ -32,16 +40,20 @@ def initialize(argv)
32 40
         :backtrace    => false,
33 41
         :monitor      => false,
34 42
       }
  43
+
  44
+      @agent = RemoteSyslog::Agent.new(:pid_file => default_pid_file)
35 45
     end
36 46
 
37  
-    def pid_file=(v)
38  
-      m = v.match(%r{^(.+/)?([^/]+?)(\.pid)?$})
39  
-      if m[1]
40  
-        @daemonize_options[:dir_mode] = :normal
41  
-        @daemonize_options[:dir] = m[1]
42  
-      end
  47
+    def is_file_writable?(file)
  48
+      directory = File.dirname(file)
43 49
 
44  
-      @app_name = m[2]
  50
+      (File.directory?(directory) && File.writable?(directory) && !File.exists?(file)) || File.writable?(file)
  51
+    end
  52
+
  53
+    def default_pid_file
  54
+      DEFAULT_PID_FILES.each do |file|
  55
+        return file if is_file_writable?(file)
  56
+      end
45 57
     end
46 58
 
47 59
     def parse
@@ -56,39 +68,55 @@ def parse
56 68
           @configfile = File.expand_path(v)
57 69
         end
58 70
         opts.on("-d", "--dest-host HOSTNAME", "Destination syslog hostname or IP (logs.papertrailapp.com)") do |v|
59  
-          @dest_host = v
  71
+          @agent.destination_host = v
60 72
         end
61 73
         opts.on("-p", "--dest-port PORT", "Destination syslog port (514)") do |v|
62  
-          @dest_port = v
  74
+          @agent.destination_port = v
63 75
         end
64 76
         opts.on("-D", "--no-detach", "Don't daemonize and detach from the terminal") do
65 77
           @no_detach = true
66 78
         end
67 79
         opts.on("-f", "--facility FACILITY", "Facility (user)") do |v|
68  
-          @facility = v
  80
+          @agent.facility = v
69 81
         end
70 82
         opts.on("--hostname HOST", "Local hostname to send from") do |v|
71  
-          @hostname = v
  83
+          @agent.hostname = v
72 84
         end
73  
-        opts.on("-P", "--pid-dir DIRECTORY", "Directory to write .pid file in (/var/run/)") do |v|
74  
-          @daemonize_options[:dir_mode] = :normal
75  
-          @daemonize_options[:dir] = v
  85
+        opts.on("-P", "--pid-dir DIRECTORY", "DEPRECATED: Directory to write .pid file in") do |v|
  86
+          puts "Warning: --pid-dir is deprecated. Please use --pid-file FILENAME instead"
  87
+          @pid_directory = v
76 88
         end
77  
-        opts.on("--pid-file FILENAME", "PID filename (<program name>.pid)") do |v|
78  
-          self.pid_file = v
  89
+        opts.on("--pid-file FILENAME", "Location of the PID file (default #{@agent.pid_file})") do |v|
  90
+          @agent.pid_file = v
79 91
         end
80 92
         opts.on("--parse-syslog", "Parse file as syslog-formatted file") do
81  
-          @parse_fields = FIELD_REGEXES['syslog']
  93
+          @agent.parse_fields = FIELD_REGEXES['syslog']
82 94
         end
83 95
         opts.on("-s", "--severity SEVERITY", "Severity (notice)") do |v|
84  
-          @severity = v
  96
+          @agent.severity = v
85 97
         end
86 98
         opts.on("--strip-color", "Strip color codes") do
87  
-          @strip_color = true
  99
+          @agent.strip_color = true
88 100
         end
89 101
         opts.on("--tls", "Connect via TCP with TLS") do
90  
-          @tls = true
  102
+          @agent.tls = true
91 103
         end
  104
+
  105
+        opts.separator ''
  106
+
  107
+        opts.on("--debug-log FILE", "Log internal debug messages") do |v|
  108
+          level = @agent.logger.level
  109
+          @agent.logger = Logger.new(v)
  110
+          @agent.logger.level = level
  111
+        end
  112
+
  113
+        severities = Logger::Severity.constants + Logger::Severity.constants.map { |s| s.downcase }
  114
+        opts.on("--debug-level LEVEL", severities, "Log internal debug messages at level") do |v|
  115
+          @agent.logger.level = Logger::Severity.const_get(v.upcase)
  116
+        end
  117
+
  118
+        opts.separator ''
  119
+
92 120
         opts.on_tail("-h", "--help", "Show this message") do
93 121
           puts opts
94 122
           exit
@@ -101,8 +129,8 @@ def parse
101 129
 
102 130
       parse_config
103 131
 
104  
-      @dest_host ||= 'logs.papertrailapp.com'
105  
-      @dest_port ||= 514
  132
+      @agent.destination_host ||= 'logs.papertrailapp.com'
  133
+      @agent.destination_port ||= 514
106 134
 
107 135
       if @files.empty?
108 136
         puts "No filenames provided and #{@configfile} not found or malformed."
@@ -114,6 +142,21 @@ def parse
114 142
       # handle relative paths before Daemonize changes the wd to / and expand wildcards
115 143
       @files = @files.flatten.map { |f| File.expand_path(f) }.uniq
116 144
 
  145
+      @agent.files = @files
  146
+
  147
+      if @pid_directory
  148
+        if @agent.pid_file
  149
+          @agent.pid_file = File.expand_path("#{@pid_directory}/#{@agent.pid_file}")
  150
+        else
  151
+          @agent.pid_file = File.expand_path("#{@pid_directory}/remote_syslog.pid")
  152
+        end
  153
+      end
  154
+
  155
+      @agent.pid_file ||= default_pid_file
  156
+    rescue OptionParser::ParseError => e
  157
+      puts "Error: #{e.message}\n\n"
  158
+      puts op
  159
+      exit
117 160
     end
118 161
 
119 162
     def parse_config
@@ -123,77 +166,49 @@ def parse_config
123 166
         @files += Array(config['files'])
124 167
 
125 168
         if config['destination'] && config['destination']['host']
126  
-          @dest_host ||= config['destination']['host']
  169
+          @agent.destination_host ||= config['destination']['host']
127 170
         end
128 171
 
129 172
         if config['destination'] && config['destination']['port']
130  
-          @dest_port ||= config['destination']['port']
  173
+          @agent.destination_port ||= config['destination']['port']
131 174
         end
132 175
 
133 176
         if config['hostname']
134  
-          @hostname = config['hostname']
  177
+          @agent.hostname = config['hostname']
135 178
         end
136 179
 
137  
-        @server_cert        = config['ssl_server_cert']
138  
-        @client_cert_chain  = config['ssl_client_cert_chain']
139  
-        @client_private_key = config['ssl_client_private_key']
  180
+        @agent.server_cert        = config['ssl_server_cert']
  181
+        @agent.client_cert_chain  = config['ssl_client_cert_chain']
  182
+        @agent.client_private_key = config['ssl_client_private_key']
140 183
 
141 184
         if config['parse_fields']
142  
-          @parse_fields = FIELD_REGEXES[config['parse_fields']] || Regexp.new(config['parse_fields'])
  185
+          @agent.parse_fields = FIELD_REGEXES[config['parse_fields']] || Regexp.new(config['parse_fields'])
143 186
         end
144 187
 
145 188
         if config['exclude_patterns']
146  
-          @exclude_pattern = Regexp.new(config['exclude_patterns'].map { |r| "(#{r})" }.join('|'))
  189
+          @agent.exclude_pattern = Regexp.new(config['exclude_patterns'].map { |r| "(#{r})" }.join('|'))
147 190
         end
148 191
       end
149 192
     end
150 193
 
151 194
     def run
152  
-      puts "Watching #{@files.length} files/paths. Sending to #{@dest_host}:#{@dest_port} (#{@tls ? 'TCP/TLS' : 'UDP'})."
  195
+      puts "Watching #{@agent.files.length} files/paths. Sending to #{@agent.destination_host}:#{@agent.destination_port} (#{@agent.tls ? 'TCP/TLS' : 'UDP'})."
153 196
 
154 197
       if @no_detach
155  
-        start
  198
+        @agent.run
156 199
       else
157  
-        Daemons.run_proc(@app_name, @daemonize_options) do
158  
-          start
159  
-        end
  200
+        daemon = Servolux::Daemon.new(:server => @agent)
  201
+        daemon.startup
160 202
       end
161  
-    end
162  
-
163  
-    def start
164  
-      EventMachine.run do
165  
-        if @tls
166  
-          connection = TlsEndpoint.new(@dest_host, @dest_port,
167  
-            :client_cert_chain => @client_cert_chain,
168  
-            :client_private_key => @client_private_key,
169  
-            :server_cert => @server_cert)
170  
-        else
171  
-          connection = UdpEndpoint.new(@dest_host, @dest_port)
172  
-        end
173  
-
174  
-        @files.each do |path|
175  
-          begin
176  
-            glob_check_interval = 60
177  
-            exclude_files       = []
178  
-            max_message_size    = 1024
179  
-
180  
-            if @tls
181  
-              max_message_size = 10240
182  
-            end
183  
-
184  
-            EventMachine::FileGlobWatchTail.new(path, RemoteSyslog::Reader,
185  
-              glob_check_interval, exclude_files,
186  
-              @dest_host, @dest_port,
187  
-              :socket => connection, :facility => @facility,
188  
-              :severity => @severity, :strip_color => @strip_color,
189  
-              :hostname => @hostname, :parse_fields => @parse_fields,
190  
-              :exclude_pattern => @exclude_pattern,
191  
-              :max_message_size => max_message_size)
192  
-          rescue Errno::ENOENT => e
193  
-            puts "#{path} not found, continuing. (#{e.message})"
194  
-          end
195  
-        end
  203
+    rescue Servolux::Daemon::StartupError => e
  204
+      case message = e.message[/^(Child raised error: )?(.*)$/, 2]
  205
+      when /#<Errno::EACCES: (.*)>$/
  206
+        puts "Error: #{$1}"
  207
+      else
  208
+        puts "Error: #{message}"
196 209
       end
  210
+    rescue Interrupt
  211
+      exit(0)
197 212
     end
198 213
   end
199 214
 end
41  lib/remote_syslog/eventmachine_reader.rb
... ...
@@ -0,0 +1,41 @@
  1
+require 'eventmachine'
  2
+require 'eventmachine-tail'
  3
+require 'em-dns-resolver'
  4
+
  5
+# Force eventmachine-tail not to change the encoding
  6
+# This will allow ruby 1.9 to deal with any file data
  7
+old_verbose, $VERBOSE = $VERBOSE, nil
  8
+EventMachine::FileTail::FORCE_ENCODING = false
  9
+$VERBOSE = old_verbose
  10
+
  11
+module RemoteSyslog
  12
+  class EventMachineReader < EventMachine::FileTail
  13
+    def initialize(path, options = {}, &block)
  14
+      @callback = options[:callback] || block
  15
+      @buffer = BufferedTokenizer.new
  16
+      @logger = options[:logger] || Logger.new(STDERR)
  17
+
  18
+      @tag = options[:program] || File.basename(path)
  19
+
  20
+      # Remove characters that can't be in a tag
  21
+      @tag = @tag.gsub(%r{[: \]\[\\]+}, '-')
  22
+
  23
+      # Make sure the tag isn't too long
  24
+      if @tag.length > 32
  25
+        @tag = @tag[0..31]
  26
+      end
  27
+
  28
+      super(path, -1)
  29
+    end
  30
+
  31
+    def receive_data(data)
  32
+      @buffer.extract(data).each do |line|
  33
+        @callback.call(@tag, line)
  34
+      end
  35
+    end
  36
+
  37
+    def on_exception(exception)
  38
+      @logger.error "Exception: #{exception.class}: #{exception.message}\n\t#{exception.backtrace.join("\n\t")}"
  39
+    end
  40
+  end
  41
+end
18  lib/remote_syslog/glob_watch.rb
... ...
@@ -0,0 +1,18 @@
  1
+require 'eventmachine-tail'
  2
+
  3
+module RemoteSyslog
  4
+  class GlobWatch < EventMachine::FileGlobWatch
  5
+    def initialize(path, interval, callback)
  6
+      super(path, interval)
  7
+      @callback = callback
  8
+    end
  9
+
  10
+    def file_found(path)
  11
+      @callback.call(path)
  12
+    end
  13
+
  14
+    def file_deleted(path)
  15
+      # Nothing to do
  16
+    end
  17
+  end
  18
+end
54  lib/remote_syslog/message_generator.rb
... ...
@@ -0,0 +1,54 @@
  1
+require 'socket'
  2
+require 'syslog_protocol'
  3
+
  4
+module RemoteSyslog
  5
+  class MessageGenerator
  6
+    COLORED_REGEXP = /\e\[(?:(?:[0-9]{1,3});){0,2}(?:[0-9]{1,3})m/
  7
+
  8
+    def initialize(socket, options = {})
  9
+      @socket = socket
  10
+
  11
+      @parse_fields     = options[:parse_fields]
  12
+      @strip_color      = options[:strip_color]
  13
+      @exclude_pattern  = options[:exclude_pattern]
  14
+      @max_message_size = options[:max_message_size] || 1024
  15
+
  16
+      @packet = SyslogProtocol::Packet.new
  17
+
  18
+      if options[:hostname] && options[:hostname] != ''
  19
+        local_hostname = options[:hostname]
  20
+      else
  21
+        local_hostname = (Socket.gethostname rescue `hostname`.chomp)[/^([^\.]+)/, 1]
  22
+
  23
+        if local_hostname.nil? || local_hostname == ''
  24
+          local_hostname = 'localhost'
  25
+        end
  26
+      end
  27
+
  28
+      @packet.hostname = local_hostname
  29
+      @packet.facility = options[:facility] || 'user'
  30
+      @packet.severity = options[:severity] || 'notice'
  31
+    end
  32
+
  33
+    def transmit(tag, message)
  34
+      return if @exclude_pattern && message =~ @exclude_pattern
  35
+
  36
+      message = message.gsub(COLORED_REGEXP, '') if @strip_color
  37
+
  38
+      packet = @packet.dup
  39
+      packet.content = message
  40
+
  41
+      if @parse_fields && message =~ @parse_fields
  42
+        packet.hostname = $2 if $2 && $2 != ''
  43
+        packet.tag      = $3 if $3 && $3 != ''
  44
+        packet.content  = $4 if $4 && $4 != ''
  45
+      end
  46
+
  47
+      unless packet.tag
  48
+        packet.tag = tag
  49
+      end
  50
+
  51
+      @socket.write(packet.assemble(@max_message_size))
  52
+    end
  53
+  end
  54
+end
87  lib/remote_syslog/reader.rb
... ...
@@ -1,87 +0,0 @@
1  
-require 'socket'
2  
-require 'eventmachine'
3  
-require 'eventmachine-tail'
4  
-require 'em-dns-resolver'
5  
-require 'syslog_protocol'
6  
-
7  
-# Force eventmachine-tail not to change the encoding
8  
-# This will allow ruby 1.9 to deal with any file data
9  
-old_verbose, $VERBOSE = $VERBOSE, nil
10  
-EventMachine::FileTail::FORCE_ENCODING = false
11  
-$VERBOSE = old_verbose
12  
-
13  
-module RemoteSyslog
14  
-  class Reader < EventMachine::FileTail
15  
-    COLORED_REGEXP = /\e\[(?:(?:[0-9]{1,3});){0,2}(?:[0-9]{1,3})m/
16  
-
17  
-    def initialize(path, destination_address, destination_port, options = {})
18  
-      super(path, -1)
19  
-
20  
-      @parse_fields = options[:parse_fields]
21  
-      @strip_color = options[:strip_color]
22  
-      @exclude_pattern = options[:exclude_pattern]
23  
-      @max_message_size = options[:max_message_size] || 1024
24  
-
25  
-      @socket = options[:socket] || UdpEndpoint.new(destination_address, destination_port)
26  
-
27  
-      @buffer = BufferedTokenizer.new
28  
-
29  
-      @packet = SyslogProtocol::Packet.new
30  
-
31  
-      if options[:hostname] && options[:hostname] != ''
32  
-        local_hostname = options[:hostname]
33  
-      else
34  
-        local_hostname = (Socket.gethostname rescue `hostname`.chomp)[/^([^\.]+)/, 1]
35  
-
36  
-        if local_hostname.nil? || local_hostname.empty?
37  
-          local_hostname = 'localhost'
38  
-        end
39  
-      end
40  
-
41  
-      @packet.hostname = local_hostname
42  
-      @packet.facility = options[:facility] || 'user'
43  
-      @packet.severity = options[:severity] || 'notice'
44  
-
45  
-      tag = options[:program] || File.basename(path) || File.basename($0)
46  
-
47  
-      # Remove characters that can't be in a tag
48  
-      tag = tag.gsub(%r{[: \]\[\\]+}, '-')
49  
-
50  
-      # Make sure the tag isn't too long
51  
-      if tag.length > 32
52  
-        tag = tag[0..31]
53  
-      end
54  
-
55  
-      @packet.tag = tag
56  
-    end
57  
-
58  
-    def receive_data(data)
59  
-      @buffer.extract(data).each do |line|
60  
-        transmit(line)
61  
-      end
62  
-    end
63  
-
64  
-    def transmit(message)
65  
-      return if @exclude_pattern && message =~ @exclude_pattern
66  
-
67  
-      message = message.gsub(COLORED_REGEXP, '') if @strip_color
68  
-
69  
-      packet = @packet.dup
70  
-      packet.content = message
71  
-
72  
-      if @parse_fields
73  
-        if message =~ @parse_fields
74  
-          packet.hostname = $2 if $2 && $2 != ''
75  
-          packet.tag      = $3 if $3 && $3 != ''
76  
-          packet.content  = $4 if $4 && $4 != ''
77  
-        end
78  
-      end
79  
-
80  
-      @socket.write(packet.assemble(@max_message_size))
81  
-    end
82  
-
83  
-    def on_exception(exception)
84  
-      puts "Exception: #{exception.class}: #{exception.message}\n\t#{exception.backtrace.join("\n\t")}"
85  
-    end
86  
-  end
87  
-end
14  lib/remote_syslog/tls_endpoint.rb
... ...
@@ -1,3 +1,5 @@
  1
+require 'eventmachine'
  2
+
1 3
 module RemoteSyslog
2 4
   class TlsEndpoint
3 5
     class Handler < EventMachine::Connection
@@ -29,12 +31,15 @@ def unbind
29 31
     attr_accessor :connection
30 32
     attr_reader :server_cert, :client_cert_chain, :client_private_key
31 33
 
  34
+    attr_reader :logger
  35
+
32 36
     def initialize(address, port, options = {})
33 37
       @address            = address
34 38
       @port               = port.to_i
35 39
       @client_cert_chain  = options[:client_cert_chain]
36 40
       @client_private_key = options[:client_private_key]
37 41
       @queue_limit        = options[:queue_limit] || 10_000
  42
+      @logger             = options[:logger] || Logger.new(STDERR)
38 43
 
39 44
       if options[:server_cert]
40 45
         @server_cert = OpenSSL::X509::Certificate.new(File.read(options[:server_cert]))
@@ -51,6 +56,12 @@ def initialize(address, port, options = {})
51 56
       connect
52 57
     end
53 58
 
  59
+    def connection=(conn)
  60
+      port, ip = Socket.unpack_sockaddr_in(conn.get_peername)
  61
+      logger.debug "Connected to #{ip}:#{port}"
  62
+      @connection = conn
  63
+    end
  64
+
54 65
     def resolve_address
55 66
       request = EventMachine::DnsResolver.resolve(@address)
56 67
       request.callback do |addrs|
@@ -63,6 +74,7 @@ def address
63 74
     end
64 75
 
65 76
     def connect
  77
+      logger.debug "Connecting to #{address}:#{@port}"
66 78
       EventMachine.connect(address, @port, TlsEndpoint::Handler, self)
67 79
     end
68 80
 
@@ -86,4 +98,4 @@ def write(value)
86 98
       end
87 99
     end
88 100
   end
89  
-end
  101
+end
9  lib/remote_syslog/udp_endpoint.rb
... ...
@@ -1,9 +1,14 @@
  1
+require 'eventmachine'
  2
+
1 3
 module RemoteSyslog
2 4
   class UdpEndpoint
3  
-    def initialize(address, port)
  5
+    attr_reader :logger
  6
+
  7
+    def initialize(address, port, options = {})
4 8
       @address = address
5 9
       @port    = port.to_i
6 10
       @socket  = EventMachine.open_datagram_socket('0.0.0.0', 0)
  11
+      @logger  = options[:logger] || Logger.new(STDERR)
7 12
 
8 13
       # Try to resolve the address
9 14
       resolve_address
@@ -29,4 +34,4 @@ def write(value)
29 34
       @socket.send_datagram(value, address, @port)
30 35
     end
31 36
   end
32  
-end
  37
+end
3  remote_syslog.gemspec
@@ -40,7 +40,8 @@ Gem::Specification.new do |s|
40 40
   ## List your runtime dependencies here. Runtime dependencies are those
41 41
   ## that are needed for an end user to actually USE your code.
42 42
   #s.add_dependency('DEPNAME', [">= 1.1.0", "< 2.0.0"])
43  
-  s.add_dependency 'daemons'
  43
+  s.add_dependency 'servolux'
  44
+  s.add_dependency 'file-tail'
44 45
   s.add_dependency 'eventmachine', [ '>= 0.12.10', '< 1.1' ]
45 46
   s.add_dependency 'eventmachine-tail'
46 47
   s.add_dependency 'syslog_protocol', [ '~> 0.9.2' ]

0 notes on commit e0cba28

Please sign in to comment.
Something went wrong with that request. Please try again.