logfoo 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/logfoo/app.rb +9 -9
- data/lib/logfoo/appenders/io_appender.rb +16 -18
- data/lib/logfoo/context.rb +85 -77
- data/lib/logfoo/entries.rb +59 -0
- data/lib/logfoo/exception_handlers/stderr_exception_handler.rb +7 -11
- data/lib/logfoo/formatters/logfmt_formatter.rb +65 -67
- data/lib/logfoo/formatters/simple_formatter.rb +35 -37
- data/lib/logfoo/integrations/hutch.rb +21 -22
- data/lib/logfoo/integrations/rack/err.rb +49 -48
- data/lib/logfoo/integrations/rack/log.rb +44 -48
- data/lib/logfoo/measure.rb +19 -0
- data/lib/logfoo/mixin.rb +11 -13
- data/lib/logfoo/version.rb +1 -1
- data/lib/logfoo.rb +2 -1
- metadata +4 -3
- data/lib/logfoo/entry.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 090c89addea5e5f294a83fc7118fc5f05eb7fcc2
|
4
|
+
data.tar.gz: e98d25ed50c2f2d443b3493b923924316b485620
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b25cfaf625776d1424efdb87e0da631657633bd56d228dac97648b3466498bebff63cb8e1b26e6b3e2d89fc7119ba14df08444ebc66b6bdb55745fddb0958e3f
|
7
|
+
data.tar.gz: 2eb571f9dc9be891d7aaaaf972f4a2e5447c457a5c1787c0ca8989a196df17a5ef2c71789196d1930a56596e68758c30f606a3a9bbdb25b6c87a714462825d33
|
data/lib/logfoo/app.rb
CHANGED
@@ -37,8 +37,8 @@ module Logfoo
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def append(
|
41
|
-
@queue.push(
|
40
|
+
def append(line)
|
41
|
+
@queue.push(line) if @thread
|
42
42
|
end
|
43
43
|
|
44
44
|
private
|
@@ -46,21 +46,21 @@ module Logfoo
|
|
46
46
|
def main_loop ; Thread.new do
|
47
47
|
begin
|
48
48
|
loop do
|
49
|
-
|
50
|
-
case
|
49
|
+
line = @queue.pop
|
50
|
+
case line
|
51
51
|
when :shutdown
|
52
52
|
break
|
53
53
|
when :boom
|
54
54
|
raise IGNORE_ME_ERROR
|
55
|
-
when
|
56
|
-
App._handle_exception(
|
55
|
+
when ErrLine
|
56
|
+
App._handle_exception(line)
|
57
57
|
else
|
58
|
-
App._append(
|
58
|
+
App._append(line)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
rescue Exception => ex
|
62
|
-
|
63
|
-
App._handle_exception(
|
62
|
+
line = ErrLine.build(logger_name: self.class, exception: ex)
|
63
|
+
App._handle_exception(line)
|
64
64
|
retry
|
65
65
|
end
|
66
66
|
end ; end
|
@@ -1,23 +1,21 @@
|
|
1
|
-
module Logfoo
|
2
|
-
|
3
|
-
|
4
|
-
@io = io || STDOUT
|
1
|
+
module Logfoo ; class IoAppender
|
2
|
+
def initialize(io = nil, formatter = nil)
|
3
|
+
@io = io || STDOUT
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
is_tty = @io.respond_to?(:tty?) && @io.tty?
|
11
|
-
@formatter = formatter || (is_tty ? SimpleFormatter.new : LogfmtFormatter.new)
|
5
|
+
if @io.respond_to?(:sync=)
|
6
|
+
@io.sync = true
|
12
7
|
end
|
13
8
|
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
is_tty = @io.respond_to?(:tty?) && @io.tty?
|
10
|
+
@formatter = formatter || (is_tty ? SimpleFormatter.new : LogfmtFormatter.new)
|
11
|
+
end
|
17
12
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
13
|
+
def call(entry)
|
14
|
+
write @formatter.call(entry)
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(body)
|
18
|
+
@io.write body
|
19
|
+
@io.flush
|
22
20
|
end
|
23
|
-
end
|
21
|
+
end ; end
|
data/lib/logfoo/context.rb
CHANGED
@@ -1,100 +1,108 @@
|
|
1
|
-
module Logfoo
|
2
|
-
class Context
|
1
|
+
module Logfoo ; class Context
|
3
2
|
|
4
|
-
|
3
|
+
attr_reader :level, :name, :thread_id, :measure
|
5
4
|
|
6
|
-
|
5
|
+
THREAD_CONTEXT = :"logfoo_context"
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
def initialize(app, name, context = nil)
|
8
|
+
@app = app
|
9
|
+
@name = name
|
10
|
+
@level = Logfoo::DEBUG
|
11
|
+
@context = context || {}
|
12
|
+
@measure = Measure.new(self)
|
13
|
+
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def level=(level)
|
16
|
+
@level = level.to_i
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
19
|
+
def []=(k,v)
|
20
|
+
if v == nil
|
21
|
+
@context.delete(k)
|
22
|
+
else
|
23
|
+
@context[k] = v
|
25
24
|
end
|
25
|
+
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
27
|
+
def context(keys = nil)
|
28
|
+
if block_given?
|
29
|
+
keys ||= {}
|
30
|
+
begin
|
31
|
+
Thread.current[THREAD_CONTEXT] ||= []
|
32
|
+
Thread.current[THREAD_CONTEXT].push(keys)
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
Thread.current[THREAD_CONTEXT].pop
|
36
|
+
if Thread.current[THREAD_CONTEXT] == []
|
37
|
+
Thread.current[THREAD_CONTEXT] = nil
|
39
38
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
memo
|
39
|
+
end
|
40
|
+
else
|
41
|
+
keys = (Thread.current[THREAD_CONTEXT] || []).inject({}) do |memo, kvs|
|
42
|
+
kvs.each do |(k,v)|
|
43
|
+
memo.merge!(k => v)
|
46
44
|
end
|
47
|
-
|
45
|
+
memo
|
48
46
|
end
|
47
|
+
@context.merge(keys)
|
49
48
|
end
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
tm = Time.now.to_f - tm
|
56
|
-
payload[:duration] = tm
|
57
|
-
self.info message, payload
|
58
|
-
re
|
51
|
+
def add(level, message, progname, &block)
|
52
|
+
lv = Logfoo::LEVELS[level]
|
53
|
+
if lv
|
54
|
+
public_send(lv.downcase, message, &block)
|
59
55
|
end
|
56
|
+
end
|
60
57
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
public_send(lv.downcase, message, &block)
|
65
|
-
end
|
58
|
+
Logfoo::LEVELS.each_with_index do |lv, idx|
|
59
|
+
define_method :"#{lv.downcase}?" do
|
60
|
+
idx >= level
|
66
61
|
end
|
62
|
+
end
|
63
|
+
|
64
|
+
Logfoo::LEVELS.each_with_index do |lv, idx|
|
65
|
+
level_id = lv.downcase.to_sym
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
define_method level_id do |message = nil, payload = nil, &block|
|
68
|
+
if idx >= level
|
69
|
+
payload = context.merge(payload || {})
|
70
|
+
message = block ? _call_log_fn(block, payload) : message
|
71
|
+
line = build_line(level_id, message, payload)
|
72
|
+
@app.append(line)
|
71
73
|
end
|
72
74
|
end
|
75
|
+
end
|
73
76
|
|
74
|
-
|
75
|
-
|
77
|
+
def _call_log_fn(fn, payload)
|
78
|
+
case fn.arity
|
79
|
+
when 0
|
80
|
+
fn.call
|
81
|
+
when 1
|
82
|
+
fn.call(payload)
|
83
|
+
else
|
84
|
+
raise RuntimeError, "invalid lambda arity, must be 0 or 1, was #{fn.arity}"
|
85
|
+
end
|
86
|
+
end
|
76
87
|
|
77
|
-
|
78
|
-
if idx >= level
|
79
|
-
message = block ? block.call : message
|
80
|
-
payload = context.merge(payload || {})
|
88
|
+
private
|
81
89
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
90
|
+
def build_line(level_id, message, payload)
|
91
|
+
if message.is_a?(Exception)
|
92
|
+
ErrLine.build(
|
93
|
+
logger_name: @name,
|
94
|
+
exception: message,
|
95
|
+
payload: payload,
|
96
|
+
level: level_id
|
97
|
+
)
|
98
|
+
else
|
99
|
+
LogLine.build(
|
100
|
+
logger_name: @name,
|
101
|
+
message: message,
|
102
|
+
payload: payload,
|
103
|
+
level: level_id
|
104
|
+
)
|
98
105
|
end
|
99
106
|
end
|
100
|
-
|
107
|
+
|
108
|
+
end ; end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Logfoo
|
2
|
+
LogLine = Struct.new(:level, :time, :logger_name, :message, :payload, :thread) do
|
3
|
+
class << self
|
4
|
+
def build(logger_name:, message:, payload: nil, level: nil)
|
5
|
+
self.new(
|
6
|
+
level || :info,
|
7
|
+
Time.now.utc,
|
8
|
+
logger_name,
|
9
|
+
message,
|
10
|
+
payload || {},
|
11
|
+
Thread.current.object_id
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
{
|
18
|
+
level: level,
|
19
|
+
time: time,
|
20
|
+
msg: message,
|
21
|
+
logger: logger_name,
|
22
|
+
}.merge!(
|
23
|
+
payload
|
24
|
+
).merge!(
|
25
|
+
thread: thread
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ErrLine = Struct.new(:level, :time, :logger_name, :exception, :payload, :thread) do
|
31
|
+
class << self
|
32
|
+
def build(logger_name:, exception:, payload: nil, level: nil)
|
33
|
+
self.new(
|
34
|
+
level || :error,
|
35
|
+
Time.now.utc,
|
36
|
+
logger_name,
|
37
|
+
exception,
|
38
|
+
payload || {},
|
39
|
+
Thread.current.object_id
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_h
|
45
|
+
{
|
46
|
+
level: level,
|
47
|
+
time: time,
|
48
|
+
msg: exception.message,
|
49
|
+
logger: logger_name,
|
50
|
+
err: exception.class.to_s,
|
51
|
+
}.merge!(
|
52
|
+
payload
|
53
|
+
).merge!(
|
54
|
+
thread: thread,
|
55
|
+
stacktrace: exception.backtrace,
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,13 +1,9 @@
|
|
1
|
-
module Logfoo
|
2
|
-
|
3
|
-
|
4
|
-
def initialize(appender = nil)
|
5
|
-
@appender = appender || IoAppender.new(STDERR)
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(entry)
|
9
|
-
@appender.call entry
|
10
|
-
end
|
1
|
+
module Logfoo ; class StderrExceptionHanlder
|
2
|
+
def initialize(appender = nil)
|
3
|
+
@appender = appender || IoAppender.new(STDERR)
|
11
4
|
end
|
12
5
|
|
13
|
-
|
6
|
+
def call(entry)
|
7
|
+
@appender.call entry
|
8
|
+
end
|
9
|
+
end ; end
|
@@ -1,85 +1,83 @@
|
|
1
1
|
require 'time'
|
2
2
|
|
3
|
-
module Logfoo
|
4
|
-
class LogfmtFormatter
|
3
|
+
module Logfoo ; class LogfmtFormatter
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
UNESCAPED_STRING = /\A[\w\.\-\+\%\,\:\;\/]*\z/i.freeze
|
6
|
+
STACKTRACE_RE = /^(.+?):(\d+):in `(.+)'$/.freeze
|
7
|
+
IGNORED_KEYS = [:time]
|
8
|
+
FLOAT_FORMAT = '%0.4f'.freeze
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
10
|
+
def call(line)
|
11
|
+
case line
|
12
|
+
when ErrLine, LogLine
|
13
|
+
format_line(line)
|
14
|
+
else
|
15
|
+
"#{remove_nl entry.to_s}\n"
|
18
16
|
end
|
17
|
+
end
|
19
18
|
|
20
|
-
|
19
|
+
private
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
def remove_nl(s)
|
22
|
+
s.tr("\n", ' ')
|
23
|
+
end
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
def format_line(line)
|
26
|
+
"#{remove_nl format_hash(line.to_h)}\n"
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
ac
|
37
|
-
end.join(" ")
|
29
|
+
def format_hash(attrs)
|
30
|
+
attrs.inject([]) do |ac, (k,v)|
|
31
|
+
if !IGNORED_KEYS.include?(k) && !(v == nil || v == "")
|
32
|
+
new_value = sanitize(k, v)
|
33
|
+
ac << "#{k}=#{new_value}"
|
38
34
|
end
|
35
|
+
ac
|
36
|
+
end.join(" ")
|
37
|
+
end
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
ac
|
47
|
-
end
|
48
|
-
if stack.any?
|
49
|
-
"\"#{stack.join("")}\""
|
39
|
+
def format_stacktrace(stack)
|
40
|
+
stack =
|
41
|
+
stack.inject([]) do |ac, line|
|
42
|
+
if line.match(STACKTRACE_RE)
|
43
|
+
ac.push "[#{$1}:#{$2}:#{$3}]"
|
50
44
|
end
|
45
|
+
ac
|
51
46
|
end
|
47
|
+
if stack.any?
|
48
|
+
"\"#{stack.join("")}\""
|
49
|
+
end
|
50
|
+
end
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
may_quote v.map{|i| i.to_s }.join(",")
|
61
|
-
end
|
62
|
-
when ::Integer, ::Symbol
|
63
|
-
v.to_s
|
64
|
-
when ::Float
|
65
|
-
FLOAT_FORMAT % v
|
66
|
-
when ::TrueClass
|
67
|
-
:t
|
68
|
-
when ::FalseClass
|
69
|
-
:f
|
70
|
-
when ::Time
|
71
|
-
v.utc.iso8601
|
72
|
-
else
|
73
|
-
may_quote v.to_s
|
74
|
-
end
|
52
|
+
def sanitize(k, v)
|
53
|
+
case v
|
54
|
+
when ::Array
|
55
|
+
if k == :stacktrace
|
56
|
+
format_stacktrace(v)
|
57
|
+
else
|
58
|
+
maybe_quote v.map{|i| i.to_s }.join(",")
|
75
59
|
end
|
60
|
+
when ::Integer, ::Symbol
|
61
|
+
v.to_s
|
62
|
+
when ::Float
|
63
|
+
FLOAT_FORMAT % v
|
64
|
+
when ::TrueClass
|
65
|
+
:t
|
66
|
+
when ::FalseClass
|
67
|
+
:f
|
68
|
+
when ::Time
|
69
|
+
v.utc.iso8601
|
70
|
+
else
|
71
|
+
maybe_quote v.to_s
|
72
|
+
end
|
73
|
+
end
|
76
74
|
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
def quote(s)
|
76
|
+
s.inspect
|
77
|
+
end
|
80
78
|
|
81
|
-
|
82
|
-
|
83
|
-
end
|
79
|
+
def maybe_quote(s)
|
80
|
+
s =~ UNESCAPED_STRING ? s : quote(s)
|
84
81
|
end
|
85
|
-
|
82
|
+
|
83
|
+
end ; end
|
@@ -1,45 +1,43 @@
|
|
1
|
-
module Logfoo
|
2
|
-
class SimpleFormatter < LogfmtFormatter
|
1
|
+
module Logfoo ; class SimpleFormatter < LogfmtFormatter
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
FORMAT = "[%5s]: %s -%s%s".freeze
|
4
|
+
BACKTRACE_LINE = "\t%s\n".freeze
|
5
|
+
EXCEPTION_LINE = "%s: %s\n".freeze
|
7
6
|
|
8
|
-
|
7
|
+
private
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
def format_line(line)
|
10
|
+
attrs = line.to_h
|
11
|
+
attrs.delete(:backtrace)
|
12
|
+
str = []
|
13
|
+
str << "#{remove_nl format_hash(line.to_h)}\n"
|
14
|
+
if entry.is_a?(ErrLine)
|
15
|
+
str << format_exception(line)
|
16
|
+
end
|
17
|
+
str.join("")
|
18
|
+
end
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
def format_exception(line)
|
21
|
+
values = []
|
22
|
+
values << (EXCEPTION_LINE % [line.exception.class, line.exception.message])
|
23
|
+
if line.exception.backtrace.is_a?(Array)
|
24
|
+
values << line.exception.backtrace.map{|l| BACKTRACE_LINE % l }.join
|
25
|
+
end
|
26
|
+
values.join
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
def format_hash(attrs)
|
30
|
+
level = attrs.delete(:level)
|
31
|
+
message = attrs.delete(:msg)
|
32
|
+
logger = attrs.delete(:logger)
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
IGNORED_KEYS.each do |f|
|
35
|
+
attrs.delete(f)
|
36
|
+
end
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
38
|
+
payload = super(attrs)
|
39
|
+
payload = payload.empty? ? "" : " [#{payload}]"
|
40
|
+
message = message.to_s.empty? ? "" : " #{message}"
|
41
|
+
FORMAT % [level.upcase, logger, message, payload]
|
44
42
|
end
|
45
|
-
end
|
43
|
+
end ; end
|
@@ -1,33 +1,32 @@
|
|
1
1
|
require 'hutch'
|
2
2
|
|
3
|
-
module Logfoo ; module Hutch
|
4
|
-
|
5
|
-
attr_reader :bunny_log, :hutch_log
|
3
|
+
module Logfoo ; module Hutch ; class ErrorHandler
|
4
|
+
attr_reader :bunny_log, :hutch_log
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
class << self
|
7
|
+
attr_accessor :handler
|
8
|
+
end
|
10
9
|
|
11
|
-
|
10
|
+
ID = 'Hutch'.freeze
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
def initialize
|
13
|
+
@hutch_log = Logfoo.get_logger(ID)
|
14
|
+
@bunny_log = Logfoo.get_logger('Bunny')
|
15
|
+
@bunny_log.level = Logfoo::WARN
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
consumer:
|
25
|
-
message_id:
|
18
|
+
def handle(message_id, payload, consumer, ex)
|
19
|
+
line = ErrLine.build(
|
20
|
+
logger_name: ID,
|
21
|
+
exception: ex,
|
22
|
+
payload: (payload || {}).merge!(
|
23
|
+
consumer: consumer,
|
24
|
+
message_id: message_id
|
26
25
|
)
|
27
|
-
|
28
|
-
|
26
|
+
)
|
27
|
+
App.instance.append(line)
|
29
28
|
end
|
30
|
-
end ; end
|
29
|
+
end ; end ; end
|
31
30
|
|
32
31
|
Logfoo::Hutch::ErrorHandler.handler = Logfoo::Hutch::ErrorHandler.new
|
33
32
|
|
@@ -1,66 +1,67 @@
|
|
1
|
-
module Logfoo
|
1
|
+
module Logfoo ; module Rack ; class Err
|
2
2
|
|
3
|
-
|
3
|
+
TEXT_PLAIN = 'text/plain'.freeze
|
4
|
+
CLEAN_RE = /\A(rack|puma|grape)\./.freeze
|
4
5
|
|
5
|
-
|
6
|
-
CLEAN_RE = /\A(rack|puma|grape)\./.freeze
|
6
|
+
FRAMEWORK_ERRORS = %w{ action_dispatch.exception sinatra.error }.freeze
|
7
7
|
|
8
|
-
|
8
|
+
INTERNAL_SERVER_ERROR = [
|
9
|
+
500,
|
10
|
+
{
|
11
|
+
R::CONTENT_TYPE => TEXT_PLAIN,
|
12
|
+
R::CONTENT_LENGTH => R::Utils::HTTP_STATUS_CODES[500].bytesize
|
13
|
+
},
|
14
|
+
[R::Utils::HTTP_STATUS_CODES[500]],
|
15
|
+
].freeze
|
9
16
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
R::CONTENT_TYPE => TEXT_PLAIN,
|
14
|
-
R::CONTENT_LENGTH => Rack::Utils::HTTP_STATUS_CODES[500].bytesize
|
15
|
-
},
|
16
|
-
[Rack::Utils::HTTP_STATUS_CODES[500]],
|
17
|
-
].freeze
|
17
|
+
def initialize(app, log = nil)
|
18
|
+
@app = app
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
end
|
21
|
+
def call(env)
|
22
|
+
response = @app.call(env)
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
if framework_error = FRAMEWORK_ERRORS.find { |k| env[k] }
|
25
|
+
append(framework_error, env)
|
26
|
+
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
response
|
29
|
+
rescue Exception => e
|
30
|
+
append(e, env)
|
31
|
+
INTERNAL_SERVER_ERROR
|
32
|
+
end
|
29
33
|
|
30
|
-
|
31
|
-
rescue Exception => e
|
32
|
-
append(e, env)
|
33
|
-
INTERNAL_SERVER_ERROR
|
34
|
-
end
|
34
|
+
private
|
35
35
|
|
36
|
-
|
36
|
+
def append(e, env)
|
37
|
+
env = clean_env(env)
|
38
|
+
env = prefix_env(env)
|
39
|
+
line = Logfoo::ErrLine.build(
|
40
|
+
logger_name: LOGGER_NAME,
|
41
|
+
exception: e,
|
42
|
+
payload: env
|
43
|
+
)
|
44
|
+
Logfoo::App.instance.append(line)
|
45
|
+
end
|
37
46
|
|
38
|
-
|
39
|
-
|
40
|
-
env
|
41
|
-
|
42
|
-
Logfoo::App.instance.append(entry)
|
47
|
+
def prefix_env(env)
|
48
|
+
env.inject({}) do |ac, (key, value)|
|
49
|
+
ac.merge!("env.#{key}" => value)
|
50
|
+
ac
|
43
51
|
end
|
52
|
+
end
|
44
53
|
|
45
|
-
|
46
|
-
|
47
|
-
|
54
|
+
def clean_env(env)
|
55
|
+
env.inject({}) do |ac, (key, value) |
|
56
|
+
case
|
57
|
+
when key =~ CLEAN_RE
|
48
58
|
ac
|
59
|
+
else
|
60
|
+
ac.merge!(key => value)
|
49
61
|
end
|
50
62
|
end
|
51
|
-
|
52
|
-
def clean_env(env)
|
53
|
-
env.inject({}) do |ac, (key, value) |
|
54
|
-
case
|
55
|
-
when key =~ CLEAN_RE
|
56
|
-
ac
|
57
|
-
else
|
58
|
-
ac.merge!(key => value)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
|
+
end ; end ; end
|
65
66
|
|
66
67
|
|
@@ -1,52 +1,48 @@
|
|
1
|
-
module Logfoo
|
2
|
-
|
3
|
-
class Log
|
4
|
-
|
5
|
-
IGNORED = %w{ /health /_ping }.freeze
|
6
|
-
HTTP_X_FORWARDED_FOR = 'HTTP_X_FORWARDED_FOR'.freeze
|
7
|
-
REMOTE_ADDR = 'REMOTE_ADDR'.freeze
|
8
|
-
|
9
|
-
def initialize(app, log = nil)
|
10
|
-
@log = log || Logfoo.get_logger(LOGGER_NAME)
|
11
|
-
@app = app
|
12
|
-
end
|
13
|
-
|
14
|
-
def call(env)
|
15
|
-
began_at = Time.now
|
16
|
-
status, header, body = @app.call(env)
|
17
|
-
header = R::Utils::HeaderHash.new(header)
|
18
|
-
body = R::BodyProxy.new(body) { log(env, status, header, began_at, body) }
|
19
|
-
[status, header, body]
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def log(env, status, header, began_at, body)
|
25
|
-
return if ignored?(status, env)
|
26
|
-
|
27
|
-
now = Time.now
|
28
|
-
addr = (env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]).to_s.split(", ").first
|
29
|
-
method = env[R::REQUEST_METHOD]
|
30
|
-
path = env[R::PATH_INFO]
|
31
|
-
|
32
|
-
payload = {
|
33
|
-
method: method,
|
34
|
-
path: path,
|
35
|
-
query: env[R::QUERY_STRING],
|
36
|
-
status: status.to_s[0..3],
|
37
|
-
len: header[R::CONTENT_LENGTH] || 0,
|
38
|
-
addr: addr,
|
39
|
-
duration: now - began_at
|
40
|
-
}
|
41
|
-
|
42
|
-
@log.info [method, path].join(" "), payload
|
43
|
-
end
|
44
|
-
|
45
|
-
def ignored?(status, env)
|
46
|
-
status > 199 && status < 299 && IGNORED.include?(env[R::PATH_INFO])
|
47
|
-
end
|
1
|
+
module Logfoo ; module Rack ; class Log
|
48
2
|
|
3
|
+
IGNORED = %w{ /health /_ping }.freeze
|
4
|
+
HTTP_X_FORWARDED_FOR = 'HTTP_X_FORWARDED_FOR'.freeze
|
5
|
+
REMOTE_ADDR = 'REMOTE_ADDR'.freeze
|
6
|
+
|
7
|
+
def initialize(app, log = nil)
|
8
|
+
@log = log || Logfoo.get_logger(LOGGER_NAME)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
began_at = Time.now
|
14
|
+
status, header, body = @app.call(env)
|
15
|
+
header = R::Utils::HeaderHash.new(header)
|
16
|
+
body = R::BodyProxy.new(body) { log(env, status, header, began_at, body) }
|
17
|
+
[status, header, body]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def log(env, status, header, began_at, body)
|
23
|
+
return if ignored?(status, env)
|
24
|
+
|
25
|
+
now = Time.now
|
26
|
+
addr = (env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]).to_s.split(", ").first
|
27
|
+
method = env[R::REQUEST_METHOD]
|
28
|
+
path = env[R::PATH_INFO]
|
29
|
+
|
30
|
+
payload = {
|
31
|
+
method: method,
|
32
|
+
path: path,
|
33
|
+
query: env[R::QUERY_STRING],
|
34
|
+
status: status.to_s[0..3],
|
35
|
+
len: header[R::CONTENT_LENGTH] || 0,
|
36
|
+
addr: addr,
|
37
|
+
duration: now - began_at
|
38
|
+
}
|
39
|
+
|
40
|
+
@log.info [method, path].join(" "), payload
|
41
|
+
end
|
42
|
+
|
43
|
+
def ignored?(status, env)
|
44
|
+
status > 199 && status < 299 && IGNORED.include?(env[R::PATH_INFO])
|
49
45
|
end
|
50
|
-
end
|
51
46
|
|
47
|
+
end ; end ; end
|
52
48
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Logfoo ; Measure = Struct.new(:source) do
|
2
|
+
def benchmark(level, message, payload, block)
|
3
|
+
payload ||= {}
|
4
|
+
time_start = Time.now.to_f
|
5
|
+
reply = source._call_log_fn(block, payload)
|
6
|
+
|
7
|
+
payload.merge!(duration: Time.now.to_f - time_start)
|
8
|
+
source.public_send(level, message, payload)
|
9
|
+
reply
|
10
|
+
end
|
11
|
+
|
12
|
+
Logfoo::LEVELS.each do |lv|
|
13
|
+
level_id = lv.downcase.to_sym
|
14
|
+
|
15
|
+
define_method level_id do |message, payload = nil, &block|
|
16
|
+
benchmark(level_id, message, payload || {}, block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end ; end
|
data/lib/logfoo/mixin.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
|
-
module Logfoo
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
1
|
+
module Logfoo ; module Mixin
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
base.log = Logfoo.get_logger(base.name)
|
5
|
+
end
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
module ClassMethods
|
8
|
+
attr_accessor :log
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
11
|
+
def log
|
12
|
+
self.class.log
|
15
13
|
end
|
16
|
-
end
|
14
|
+
end ; end
|
data/lib/logfoo/version.rb
CHANGED
data/lib/logfoo.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logfoo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Galinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -99,7 +99,7 @@ files:
|
|
99
99
|
- lib/logfoo/app.rb
|
100
100
|
- lib/logfoo/appenders/io_appender.rb
|
101
101
|
- lib/logfoo/context.rb
|
102
|
-
- lib/logfoo/
|
102
|
+
- lib/logfoo/entries.rb
|
103
103
|
- lib/logfoo/exception_handlers/stderr_exception_handler.rb
|
104
104
|
- lib/logfoo/formatters/logfmt_formatter.rb
|
105
105
|
- lib/logfoo/formatters/simple_formatter.rb
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/logfoo/integrations/rack.rb
|
108
108
|
- lib/logfoo/integrations/rack/err.rb
|
109
109
|
- lib/logfoo/integrations/rack/log.rb
|
110
|
+
- lib/logfoo/measure.rb
|
110
111
|
- lib/logfoo/mixin.rb
|
111
112
|
- lib/logfoo/version.rb
|
112
113
|
- logfoo.gemspec
|
data/lib/logfoo/entry.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module Logfoo
|
2
|
-
Entry = Struct.new(:level, :time, :logger_name, :message, :payload, :thread) do
|
3
|
-
def to_h
|
4
|
-
{
|
5
|
-
level: level || :info,
|
6
|
-
time: time || Time.now,
|
7
|
-
msg: message,
|
8
|
-
logger: logger_name,
|
9
|
-
}.merge!(
|
10
|
-
payload || {}
|
11
|
-
).merge!(
|
12
|
-
thread: thread
|
13
|
-
)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
ExceptionEntry = Struct.new(:level, :time, :logger_name, :exception, :payload, :thread) do
|
18
|
-
class << self
|
19
|
-
def build(logger_name, ex, payload = nil, options = {})
|
20
|
-
self.new(
|
21
|
-
options[:level],
|
22
|
-
Time.now,
|
23
|
-
logger_name,
|
24
|
-
ex,
|
25
|
-
payload,
|
26
|
-
Thread.current.object_id
|
27
|
-
)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_h
|
32
|
-
{
|
33
|
-
level: level || :error,
|
34
|
-
time: time || Time.now,
|
35
|
-
msg: exception.message,
|
36
|
-
logger: logger_name,
|
37
|
-
err: exception.class.to_s,
|
38
|
-
}.merge!(
|
39
|
-
payload || {}
|
40
|
-
).merge!(
|
41
|
-
thread: thread,
|
42
|
-
stacktrace: exception.backtrace,
|
43
|
-
)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|