remote_syslog 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- gem 'daemons'
2
- gem 'eventmachine'
3
- gem 'eventmachine-tail'
1
+ source :rubygems
2
+
3
+ gemspec
data/README.md CHANGED
@@ -46,21 +46,26 @@ specified as arguments to the remote_syslog daemon. More below.
46
46
  -p, --dest-port PORT Destination syslog port (514)
47
47
  -P, --pid-dir DIRECTORY Directory to write .pid file in (/var/run/)
48
48
  -s, --severity SEVERITY Severity (notice)
49
+ --strip-color Strip color codes
49
50
  -h, --help Show this message
51
+
50
52
 
51
53
 
52
54
  ## Example
53
55
 
54
- Daemonize, collecting from files mentioned in ./config/logs.yml as well as
55
- /var/log/mysqld.log:
56
+ Daemonize, collecting from files mentioned in `./config/logs.yml` as well as
57
+ `/var/log/mysqld.log`:
58
+
56
59
  $ remote_syslog -c configs/logs.yml -p 12345 /var/log/mysqld.log
57
60
 
58
- Stay attached to the terminal, look for and use /etc/log_files.yml if it exists,
59
- write PID to /tmp/remote_syslog.pid, and send with facility local0:
61
+ Stay attached to the terminal, look for and use `/etc/log_files.yml` if it
62
+ exists, write PID to `/tmp/remote_syslog.pid`, and send with facility local0:
63
+
60
64
  $ remote_syslog -d a.server.com -f local0 -P /tmp /var/log/mysqld.log
61
65
 
62
66
  remote_syslog will daemonize by default. A sample init file is in the gem as
63
67
  remote_syslog.init.d. You may be able to:
68
+
64
69
  $ cp examples/remote_syslog.init.d /etc/init.d/remote_syslog
65
70
 
66
71
 
@@ -73,9 +78,11 @@ The gem comes with a sample config. Optionally:
73
78
  $ cp examples/log_files.yml.example /etc/log_files.yml
74
79
 
75
80
  log_files.yml has filenames to log from (as an array) and hostname and port
76
- to log to (as a hash). Only 1 destination server is supported; the command-line
77
- argument wins. Filenames given on the command line are additive to those
78
- in the config file.
81
+ to log to (as a hash). Wildcards are supported using * and standard shell
82
+ globbing. Filenames given on the command line are additive to those in
83
+ the config file.
84
+
85
+ Only 1 destination server is supported; the command-line argument wins.
79
86
 
80
87
  files: [/var/log/httpd/access_log, /var/log/httpd/error_log, /var/log/mysqld.log, /var/run/mysqld/mysqld-slow.log]
81
88
  destination:
@@ -85,7 +92,6 @@ in the config file.
85
92
 
86
93
  ## Reporting bugs
87
94
 
88
-
89
95
  1. See whether the issue has already been reported: <https://github.com/papertrail/remote_syslog/issues/>
90
96
  2. If you don't find one, create an issue with a repro case.
91
97
 
data/bin/remote_syslog CHANGED
@@ -14,18 +14,19 @@ require 'remote_syslog'
14
14
  def remote_syslog_daemon(args)
15
15
  options = {
16
16
  :configfile => '/etc/log_files.yml',
17
- :dest_host => 'logs.papertrailapp.com',
18
- :dest_port => 514
17
+ :dest_host => 'logs.papertrailapp.com',
18
+ :dest_port => 514
19
19
  }
20
20
  daemonize_options = {
21
- :app_name => File.basename($0) || "remote_syslog",
22
- :ARGV => ['start'],
23
- :dir_mode => :system,
24
- :multiple => false,
25
- :ontop => false,
26
- :mode => :exec,
27
- :backtrace => false,
28
- :monitor => false
21
+ :app_name => File.basename($0) || "remote_syslog",
22
+ :ARGV => ['start'],
23
+ :dir_mode => :system,
24
+ :multiple => false,
25
+ :ontop => false,
26
+ :mode => :exec,
27
+ :backtrace => false,
28
+ :monitor => false,
29
+ :strip_color => false
29
30
  }
30
31
 
31
32
  op = OptionParser.new do |opts|
@@ -61,6 +62,9 @@ def remote_syslog_daemon(args)
61
62
  opts.on("-s", "--severity SEVERITY", "Severity (notice)") do |v|
62
63
  options[:severity] = v.upcase
63
64
  end
65
+ opts.on("--strip-color", "Strip color codes") do
66
+ options[:strip_color] = true
67
+ end
64
68
  opts.on_tail("-h", "--help", "Show this message") do
65
69
  puts opts
66
70
  exit
@@ -97,9 +101,9 @@ def remote_syslog_daemon(args)
97
101
  files.each do |path|
98
102
  begin
99
103
  EventMachine::file_tail(File.expand_path(path), RemoteSyslog::Reader,
100
- options[:dest_host], options[:dest_port],
101
- { :socket => socket, :facility => options[:facility],
102
- :severity => options[:severity] })
104
+ options[:dest_host], options[:dest_port],
105
+ :socket => socket, :facility => options[:facility],
106
+ :severity => options[:severity], :strip_color => options[:strip_color])
103
107
 
104
108
  rescue Errno::ENOENT => e
105
109
  puts "#{File.expand_path(path)} not found, continuing. (#{e.message})"
@@ -1,4 +1,4 @@
1
- files: [/var/log/httpd/access_log, /var/log/httpd/error_log, /var/log/mysqld.log, /var/run/mysqld/mysqld-slow.log]
1
+ files: [/var/log/httpd/access_log, /var/log/httpd/error_log, /opt/misc/*, /var/log/mysqld.log, /var/run/mysqld/mysqld-slow.log]
2
2
  destination:
3
3
  host: logs.papertrailapp.com
4
4
  port: 12345 # optional, defaults to 514
@@ -0,0 +1,9 @@
1
+ # Supervisor conf file for stock Ubuntu 11.04 install
2
+ [program:remote_syslog]
3
+
4
+ command=/var/lib/gems/1.8/bin/remote_syslog --no-detach
5
+ user=root
6
+ group=root
7
+ autostart=true
8
+ autorestart=true
9
+ redirect_stderr=true
@@ -1,57 +1,69 @@
1
+ require 'eventmachine'
2
+ require 'eventmachine-tail'
3
+ require 'em-dns-resolver'
4
+ require 'syslog_protocol'
5
+
1
6
  module RemoteSyslog
2
7
  class Reader < EventMachine::FileTail
3
- def initialize(path, dest_addr, dest_port, options = {})
4
- @dest_addr = dest_addr
5
- @dest_port = dest_port.to_i
6
-
8
+ COLORED_REGEXP = /\e\[(?:(?:[34][0-7]|[0-9]);){0,2}(?:[34][0-7]|[0-9])m/
9
+
10
+ def initialize(path, destination_address, destination_port, options = {})
11
+ super(path, -1)
12
+
13
+ @destination_address = destination_address
14
+ @destination_port = destination_port.to_i
15
+
16
+ @strip_color = options[:strip_color]
17
+
7
18
  @socket = options[:socket] || EventMachine.open_datagram_socket('0.0.0.0', 0)
8
- @program = options[:program] || File.basename(path) || 'remote_syslog'
9
- @hostname = options[:hostname] || `hostname`.strip
10
- @hostname = 'localhost' unless @hostname && @hostname != ''
11
-
12
- if options[:severity]
13
- @severity = severity_value(options[:severity]) || raise(ArgumentError, "Invalid severity: #{options[:severity]} (valid: #{severities.keys.join(', ')})")
14
- else
15
- @severity = severity_value(:notice)
19
+
20
+ @buffer = BufferedTokenizer.new
21
+
22
+ @packet = SyslogProtocol::Packet.new
23
+
24
+ local_hostname = options[:hostname] || (Socket.gethostname rescue `hostname`.chomp)
25
+ if local_hostname.nil? || local_hostname.empty?
26
+ local_hostname = 'localhost'
16
27
  end
17
-
18
- if options[:facility]
19
- @facility = facility_value(options[:facility]) || raise(ArgumentError, "Invalid facility: #{options[:facility]} (valid: #{facilities.keys.join(', ')}")
20
- else
21
- @facility = facility_value(:user)
28
+
29
+ @packet.hostname = local_hostname
30
+ @packet.facility = options[:facility] || 'user'
31
+ @packet.severity = options[:severity] || 'notice'
32
+ @packet.tag = options[:program] || File.basename(path) || File.basename($0)
33
+
34
+ # Try to resolve the destination address
35
+ resolve_destination_address
36
+
37
+ # Every 60 seconds we'll see if the address has changed
38
+ EventMachine.add_periodic_timer(60) do
39
+ resolve_destination_address
22
40
  end
41
+ end
23
42
 
24
- super(path, -1)
25
- @buffer = BufferedTokenizer.new
43
+ def resolve_destination_address
44
+ request = EventMachine::DnsResolver.resolve(@destination_address)
45
+ request.callback do |addrs|
46
+ @cached_destination_ip = addrs.first
47
+ end
26
48
  end
27
-
49
+
28
50
  def receive_data(data)
29
51
  @buffer.extract(data).each do |line|
30
52
  transmit(line)
31
53
  end
32
54
  end
33
55
 
56
+ def destination_address
57
+ @cached_destination_ip || @destination_address
58
+ end
59
+
34
60
  def transmit(message)
35
- time ||= Time.now
36
- day = time.strftime('%b %d').sub(/0(\d)/, ' \\1')
61
+ message = message.gsub(COLORED_REGEXP, '') if @strip_color
37
62
 
38
- @socket.send_datagram("<#{(@facility) + @severity}>#{day} #{time.strftime('%T')} #{@hostname} #{@program}: #{message}", @dest_addr, @dest_port)
39
- end
40
-
41
- def facility_value(f)
42
- f.is_a?(Integer) ? f*8 : facilities[f.to_sym]
43
- end
44
-
45
- def severity_value(s)
46
- s.is_a?(Integer) ? s : severities[s.to_sym]
47
- end
48
-
49
- def facilities
50
- Levels::FACILITIES
51
- end
52
-
53
- def severities
54
- Levels::SEVERITIES
63
+ packet = @packet.dup
64
+ packet.content = message
65
+
66
+ @socket.send_datagram(packet.assemble, destination_address, @destination_port)
55
67
  end
56
68
  end
57
69
  end
data/lib/remote_syslog.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module RemoteSyslog
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
4
4
 
5
5
  require 'remote_syslog/levels'
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
8
8
  ## If your rubyforge_project name is different, then edit it and comment out
9
9
  ## the sub! line in the Rakefile
10
10
  s.name = 'remote_syslog'
11
- s.version = '1.0.0'
12
- s.date = '2011-03-22'
11
+ s.version = '1.1.0'
12
+ s.date = '2011-05-26'
13
13
  s.rubyforge_project = 'remote_syslog'
14
14
 
15
15
  ## Make sure your summary is short. The description may be as long
@@ -20,18 +20,14 @@ Gem::Specification.new do |s|
20
20
  ## List the primary authors. If there are a bunch of authors, it's probably
21
21
  ## better to set the email to an email list or something. If you don't have
22
22
  ## a custom homepage, consider using your GitHub URL or the like.
23
- s.authors = ['Papertrail']
24
- s.email = 'troy@sevenscale.com'
23
+ s.authors = [ 'Troy Davis', 'Eric Lindvall' ]
24
+ s.email = [ 'troy@sevenscale.com', 'eric@sevenscale.com' ]
25
25
  s.homepage = 'http://github.com/papertrail/remote_syslog'
26
26
 
27
27
  ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
28
28
  ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
29
29
  s.require_paths = %w[lib]
30
30
 
31
- ## This sections is only necessary if you have C extensions.
32
- #s.require_paths << 'ext'
33
- #s.extensions = %w[ext/extconf.rb]
34
-
35
31
  ## If your gem includes any executables, list them here.
36
32
  s.executables = ['remote_syslog']
37
33
  s.default_executable = 'remote_syslog'
@@ -47,6 +43,8 @@ Gem::Specification.new do |s|
47
43
  s.add_dependency 'daemons'
48
44
  s.add_dependency 'eventmachine'
49
45
  s.add_dependency 'eventmachine-tail'
46
+ s.add_dependency 'syslog_protocol'
47
+ s.add_dependency 'em-resolv-replace'
50
48
 
51
49
  ## List your development dependencies here. Development dependencies are
52
50
  ## those that are only needed during development
@@ -64,6 +62,7 @@ Gem::Specification.new do |s|
64
62
  bin/remote_syslog
65
63
  examples/log_files.yml.example
66
64
  examples/remote_syslog.init.d
65
+ examples/remote_syslog.supervisor.conf
67
66
  lib/remote_syslog.rb
68
67
  lib/remote_syslog/levels.rb
69
68
  lib/remote_syslog/reader.rb
metadata CHANGED
@@ -1,21 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remote_syslog
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
+ - 1
8
9
  - 0
9
- - 0
10
- version: 1.0.0
10
+ version: 1.1.0
11
11
  platform: ruby
12
12
  authors:
13
- - Papertrail
13
+ - Troy Davis
14
+ - Eric Lindvall
14
15
  autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-03-22 00:00:00 -07:00
19
+ date: 2011-05-26 00:00:00 -07:00
19
20
  default_executable: remote_syslog
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
@@ -60,8 +61,38 @@ dependencies:
60
61
  version: "0"
61
62
  type: :runtime
62
63
  version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ name: syslog_protocol
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ type: :runtime
77
+ version_requirements: *id004
78
+ - !ruby/object:Gem::Dependency
79
+ name: em-resolv-replace
80
+ prerelease: false
81
+ requirement: &id005 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ type: :runtime
91
+ version_requirements: *id005
63
92
  description: Lightweight daemon to tail one or more log files and transmit UDP syslog messages to a remote syslog host (centralized log aggregation). Generates UDP packets itself instead of depending on a system syslog daemon, so it doesn't affect system-wide logging configuration.
64
- email: troy@sevenscale.com
93
+ email:
94
+ - troy@sevenscale.com
95
+ - eric@sevenscale.com
65
96
  executables:
66
97
  - remote_syslog
67
98
  extensions: []
@@ -77,6 +108,7 @@ files:
77
108
  - bin/remote_syslog
78
109
  - examples/log_files.yml.example
79
110
  - examples/remote_syslog.init.d
111
+ - examples/remote_syslog.supervisor.conf
80
112
  - lib/remote_syslog.rb
81
113
  - lib/remote_syslog/levels.rb
82
114
  - lib/remote_syslog/reader.rb