log2sock 0.0.5
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/.gitignore +1 -0
- data/LICENSE +21 -0
- data/README.md +48 -0
- data/bin/log2read +32 -0
- data/lib/log2sock.rb +199 -0
- data/log2sock.gemspec +27 -0
- metadata +53 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2013 Alex Williams, Unscramble <license@unscramble.jp>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# log2sock
|
2
|
+
|
3
|
+
log2sock allows you to send logs to a UNIX domain socket. Its usage is similar to the Ruby 'logger' class, except with slightly less features.
|
4
|
+
|
5
|
+
## Reading logs on a socket
|
6
|
+
|
7
|
+
A small tool is included in this gem to help you read log messages on a UNIX domain socket.
|
8
|
+
|
9
|
+
It's called `log2read`. It takes 1 argument which is the path/filename of the socket you want to create and listen on.
|
10
|
+
|
11
|
+
Example:
|
12
|
+
|
13
|
+
```
|
14
|
+
# Let's assume you're using RBENV
|
15
|
+
~/.rbenv/shims/log2read /tmp/mylogs.sock
|
16
|
+
```
|
17
|
+
|
18
|
+
## Writing logs to a socket
|
19
|
+
|
20
|
+
Add this to your app and start logging stuff to a UNIX domain socket.
|
21
|
+
|
22
|
+
Example:
|
23
|
+
|
24
|
+
```
|
25
|
+
require 'log2sock'
|
26
|
+
|
27
|
+
logger = Log2sock.new("/tmp/mylogs.sock")
|
28
|
+
logger.level(Log2sock::INFO)
|
29
|
+
logger.debug("This is a debug message") # This won't be displayed
|
30
|
+
logger.info("This is an info message") # This will be displayed
|
31
|
+
logger.debug { "This is something really stupid #{5/0}" } # This won't be evaluated
|
32
|
+
logger.level(Log2sock::DEBUG)
|
33
|
+
logger.debug { "This is something really stupid #{5/0}" } # lulz
|
34
|
+
```
|
35
|
+
|
36
|
+
## Notes
|
37
|
+
|
38
|
+
* If the socket can't be used (ex: if it doesn't exist), the logs will be sent to STDOUT.
|
39
|
+
* The default socket is: `/tmp/log2.sock` which also exists in the CONSTANT `Log2sock::DEFAULT_SOCKET`
|
40
|
+
* There are 6 log levels: `DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN`
|
41
|
+
* Each log level is a constant (ex: `Log2sock::INFO`)
|
42
|
+
* The default log level is: `Log2sock::DEBUG`
|
43
|
+
* The `log2read` tool creates a socket with file permissions 750
|
44
|
+
* Press Ctrl+C to exit the log2read tool
|
45
|
+
|
46
|
+
## Requirements
|
47
|
+
|
48
|
+
* Ruby 1.9.x or greater
|
data/bin/log2read
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'log2sock'
|
4
|
+
|
5
|
+
socketfile = !ARGV.empty? ? ARGV[0] : Log2sock::DEFAULT_SOCKET
|
6
|
+
|
7
|
+
begin
|
8
|
+
if File.exist?(socketfile)
|
9
|
+
puts "UNIX domain socket already exists, removing it first: #{socketfile}"
|
10
|
+
File.unlink(socketfile)
|
11
|
+
end
|
12
|
+
server = UNIXServer.new(socketfile)
|
13
|
+
|
14
|
+
%x[chmod 750 #{socketfile}]
|
15
|
+
puts "UNIX domain socket created at: #{socketfile}"
|
16
|
+
puts "========"
|
17
|
+
puts "Press Ctrl+C to terminate the reader"
|
18
|
+
puts "========"
|
19
|
+
|
20
|
+
loop {
|
21
|
+
Thread.start(server.accept) do |client|
|
22
|
+
while line = client.gets
|
23
|
+
puts line
|
24
|
+
end
|
25
|
+
client.close
|
26
|
+
end
|
27
|
+
}
|
28
|
+
rescue Interrupt => e
|
29
|
+
puts "Terminating the reader and removing the socket"
|
30
|
+
File.unlink(socketfile)
|
31
|
+
exit
|
32
|
+
end
|
data/lib/log2sock.rb
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
class Log2sock
|
2
|
+
require 'socket'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
DEFAULT_SOCKET = "/tmp/log2.sock"
|
6
|
+
|
7
|
+
# Log levels
|
8
|
+
DEBUG = 'debug'
|
9
|
+
INFO = 'info'
|
10
|
+
WARN = 'warn'
|
11
|
+
ERROR = 'error'
|
12
|
+
FATAL = 'fatal'
|
13
|
+
UNKNOWN = 'unknown'
|
14
|
+
|
15
|
+
# Public: initializer
|
16
|
+
#
|
17
|
+
# log2sockfile - The String filename of the UNIX domain socket
|
18
|
+
# (default: Log2sock::DEFAULT_SOCKET)
|
19
|
+
#
|
20
|
+
# This method performs the following tasks:
|
21
|
+
# * set the default log severity level
|
22
|
+
# * obtain the process ID number
|
23
|
+
# * set the socket file name
|
24
|
+
# * try to open the socket for writing
|
25
|
+
# * revert to STDOUT if the socket can't be opened
|
26
|
+
#
|
27
|
+
# Examples:
|
28
|
+
#
|
29
|
+
# logger = Log2sock.new("/tmp/mylogs.sock")
|
30
|
+
#
|
31
|
+
# logger = Log2sock.new
|
32
|
+
#
|
33
|
+
# Returns nothing useful
|
34
|
+
#
|
35
|
+
def initialize(log2sockfile = DEFAULT_SOCKET)
|
36
|
+
@loglevel = DEBUG
|
37
|
+
@pid = Process.pid
|
38
|
+
|
39
|
+
begin
|
40
|
+
@socketfile = log2sockfile
|
41
|
+
@socket = UNIXSocket.open(@socketfile)
|
42
|
+
rescue Exception => e
|
43
|
+
set_socket_stdout(e)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: send a message to the socket or STDOUT
|
48
|
+
#
|
49
|
+
# msg - The optional String unescaped message you want to log (default: nil)
|
50
|
+
# severity - The String or CONSTANT log level severity of the message
|
51
|
+
# &block - The String reference block which doesn't necessarily get evaluated
|
52
|
+
#
|
53
|
+
# This method performs the following tasks:
|
54
|
+
# * create a timestamp similar to this: 2013-02-07T03:58:09.902243
|
55
|
+
# * create a prefix for each log message with the severity, timestamp and process id
|
56
|
+
# * verifies if a block exists before setting the output message
|
57
|
+
# * tries to output the message to the socket or STDOUT
|
58
|
+
#
|
59
|
+
# Examples:
|
60
|
+
#
|
61
|
+
# logger.message("This is a debug message", Log2sock::DEBUG)
|
62
|
+
#
|
63
|
+
# logger.message(Log2sock::INFO) { "This is a debug message" }
|
64
|
+
#
|
65
|
+
# Returns nothing useful
|
66
|
+
#
|
67
|
+
def message(msg = nil, severity, &block)
|
68
|
+
d = DateTime.now
|
69
|
+
timestamp = d.strftime("%Y-%m-%dT%H:%M:%S.%6N")
|
70
|
+
# we use rjust(7) because the longest 'severity' is "unknown" which is 7 chars long
|
71
|
+
prefix = "#{severity[0].upcase}, [#{timestamp} \##{@pid}] #{severity.upcase.rjust(7)} -- :"
|
72
|
+
|
73
|
+
if block_given?
|
74
|
+
message = yield
|
75
|
+
else
|
76
|
+
message = msg
|
77
|
+
end
|
78
|
+
|
79
|
+
begin
|
80
|
+
@socket.puts "#{prefix} #{message}"
|
81
|
+
rescue Exception => e
|
82
|
+
# If the socket generates and exception, set the output
|
83
|
+
# to STDOUT for future calls to message()
|
84
|
+
set_socket_stdout(e)
|
85
|
+
@socket.puts "#{prefix} #{message}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Public: set the log severity level
|
90
|
+
#
|
91
|
+
# level - The String or CONSTANT log level severity (default: nil)
|
92
|
+
#
|
93
|
+
# Notes:
|
94
|
+
# * if the log level is not sent as a parameter, it simply returns the current log level
|
95
|
+
# * if the log level is sent as a parameter, the new log level is set
|
96
|
+
#
|
97
|
+
# Examples:
|
98
|
+
#
|
99
|
+
# puts logger.level
|
100
|
+
#
|
101
|
+
# logger.level(Log2sock::INFO)
|
102
|
+
#
|
103
|
+
# Returns The String of the current log severity level
|
104
|
+
#
|
105
|
+
def level(level = nil)
|
106
|
+
@loglevel = level unless level == nil
|
107
|
+
return @loglevel
|
108
|
+
end
|
109
|
+
|
110
|
+
# Public: generate a <SEVERITY> log message
|
111
|
+
#
|
112
|
+
# msg - The String unescaped message you want to log (default: nil)
|
113
|
+
# &block - The String reference block which doesn't necessarily get evaluated
|
114
|
+
#
|
115
|
+
# Notes:
|
116
|
+
# * calls the message() method only if the log severity level is is equal or higher priority
|
117
|
+
# * if a block is given, it will only be evaluated if the conditions are met
|
118
|
+
# * same functionality for all 6 log severity levels
|
119
|
+
#
|
120
|
+
# Examples:
|
121
|
+
#
|
122
|
+
# logger.warn("This is a warn message")
|
123
|
+
#
|
124
|
+
# logger.info { "This is an info message" }
|
125
|
+
#
|
126
|
+
# logger.level(Log2sock::INFO)
|
127
|
+
# logger.debug { "This is an unevaluated debug message #{5/0}" } # <-- only evaluated if severity is DEBUG
|
128
|
+
#
|
129
|
+
# Returns true if the message() is called, false if it isn't
|
130
|
+
#
|
131
|
+
def debug(msg = nil, &block)
|
132
|
+
if [DEBUG].include? @loglevel
|
133
|
+
message(msg, DEBUG, &block)
|
134
|
+
return true
|
135
|
+
end
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
|
139
|
+
def info(msg = nil, &block)
|
140
|
+
if [DEBUG, INFO].include? @loglevel
|
141
|
+
message(msg, INFO, &block)
|
142
|
+
return true
|
143
|
+
end
|
144
|
+
return false
|
145
|
+
end
|
146
|
+
|
147
|
+
def warn(msg = nil, &block)
|
148
|
+
if [DEBUG, INFO, WARN].include? @loglevel
|
149
|
+
message(msg, WARN, &block)
|
150
|
+
return true
|
151
|
+
end
|
152
|
+
return false
|
153
|
+
end
|
154
|
+
|
155
|
+
def error(msg = nil, &block)
|
156
|
+
if [DEBUG, INFO, WARN, ERROR].include? @loglevel
|
157
|
+
message(msg, ERROR, &block)
|
158
|
+
return true
|
159
|
+
end
|
160
|
+
return false
|
161
|
+
end
|
162
|
+
|
163
|
+
def fatal(msg = nil, &block)
|
164
|
+
if [DEBUG, INFO, WARN, ERROR, FATAL].include? @loglevel
|
165
|
+
message(msg, FATAL, &block)
|
166
|
+
return true
|
167
|
+
end
|
168
|
+
return false
|
169
|
+
end
|
170
|
+
|
171
|
+
def unknown(msg = nil, &block)
|
172
|
+
if [DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN].include? @loglevel
|
173
|
+
message(msg, UNKNOWN, &block)
|
174
|
+
return true
|
175
|
+
end
|
176
|
+
return false
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
# Private: set the socket log output to STDOUT
|
182
|
+
#
|
183
|
+
# error - The String error message explaining why we're logging to STDOUT instead of a UNIX domain socket
|
184
|
+
#
|
185
|
+
# Notes:
|
186
|
+
# * if this is called, we set the output using the global $stdout variable
|
187
|
+
# * prints the error message to STDOUT, obviously
|
188
|
+
#
|
189
|
+
# Example:
|
190
|
+
#
|
191
|
+
# set_socket_stdout("Exception error message")
|
192
|
+
#
|
193
|
+
# Returns nothing useful
|
194
|
+
#
|
195
|
+
def set_socket_stdout(error)
|
196
|
+
@socket = $stdout
|
197
|
+
@socket.puts "Error opening socket, logging to STDOUT: #{error}"
|
198
|
+
end
|
199
|
+
end
|
data/log2sock.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require "base64"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'log2sock'
|
8
|
+
s.version = '0.0.5'
|
9
|
+
|
10
|
+
s.date = Date.today.to_s
|
11
|
+
|
12
|
+
s.summary = "log2sock allows you to send logs to a UNIX domain socket"
|
13
|
+
s.description = "#{s.summary}. Its usage is similar to the Ruby 'logger' class, except with slightly less features."
|
14
|
+
|
15
|
+
s.author = 'Alex Williams'
|
16
|
+
s.email = Base64.decode64("YXdpbGxpYW1zQGFsZXh3aWxsaWFtcy5jYQ==\n")
|
17
|
+
|
18
|
+
s.homepage = 'http://unscramble.co.jp'
|
19
|
+
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.bindir = 'bin'
|
22
|
+
s.executables = %w[log2read]
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
|
25
|
+
license = 'MIT'
|
26
|
+
s.required_ruby_version = ::Gem::Requirement.new("~> 1.9")
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: log2sock
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alex Williams
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-07 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: log2sock allows you to send logs to a UNIX domain socket. Its usage is
|
15
|
+
similar to the Ruby 'logger' class, except with slightly less features.
|
16
|
+
email: !binary |-
|
17
|
+
YXdpbGxpYW1zQGFsZXh3aWxsaWFtcy5jYQ==
|
18
|
+
executables:
|
19
|
+
- log2read
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- .gitignore
|
24
|
+
- LICENSE
|
25
|
+
- README.md
|
26
|
+
- bin/log2read
|
27
|
+
- lib/log2sock.rb
|
28
|
+
- log2sock.gemspec
|
29
|
+
homepage: http://unscramble.co.jp
|
30
|
+
licenses: []
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.9'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 1.8.23
|
50
|
+
signing_key:
|
51
|
+
specification_version: 3
|
52
|
+
summary: log2sock allows you to send logs to a UNIX domain socket
|
53
|
+
test_files: []
|