loggerator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/generators/loggerator/log_generator.rb +17 -0
- data/lib/generators/templates/log.rb.erb +4 -0
- data/lib/loggerator.rb +1 -0
- data/lib/loggerator/loggerator.rb +146 -0
- data/lib/loggerator/metrics.rb +41 -0
- data/lib/loggerator/middleware.rb +7 -0
- data/lib/loggerator/middleware/request_id.rb +55 -0
- data/lib/loggerator/middleware/request_store.rb +14 -0
- data/lib/loggerator/namespace.rb +22 -0
- data/lib/loggerator/rails.rb +22 -0
- data/lib/loggerator/request_store.rb +24 -0
- data/lib/loggerator/test.rb +32 -0
- data/test/loggerator/middleware/request_id_test.rb +33 -0
- data/test/loggerator/middleware/request_store_test.rb +40 -0
- data/test/loggerator/request_store_test.rb +35 -0
- data/test/loggerator_test.rb +73 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b09044e8590344b2433a544b15a853d63e92d06b
|
4
|
+
data.tar.gz: 1fc9edb37658480a85d314177440e4dd79d568c8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: baf7c00883dcfec5e32f33feeabb28d9ecf541a0cfe3c72f503b62740d18d38f2465c71dd676da26d7056c33acad54eac304e5274a61f731037787d8f59237e2
|
7
|
+
data.tar.gz: f5912098321f92a9d449e3029a53cc3c33609531e5c0ea5faf02ee6f8793bb75a5fc742689056fe6ec6c247371e82d7149b26b304185de5fca2662d96079d401
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Loggerator
|
2
|
+
class LogGenerator < Rails::Generators::Base
|
3
|
+
|
4
|
+
desc "Creates an initializer for Loggerator logs at config/initializer/log.rb"
|
5
|
+
class_option :a, banner: "APP_NAME", desc: "Specify APP_NAME instead of the one defined by Rails"
|
6
|
+
source_root File.expand_path("../../templates", __FILE__)
|
7
|
+
|
8
|
+
def create_config_file
|
9
|
+
template "log.rb.erb", "config/initializers/log.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def app_name
|
14
|
+
options[:a] || Rails.root.basename
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/loggerator.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'loggerator/loggerator'
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require_relative 'request_store'
|
2
|
+
require_relative 'middleware'
|
3
|
+
|
4
|
+
module Loggerator
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def self.included(mod)
|
8
|
+
mod.extend self
|
9
|
+
end
|
10
|
+
|
11
|
+
def log(data, &block)
|
12
|
+
log_to_stream(stdout, merge_log_contexts(data), &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def log_error(e, data = {})
|
16
|
+
exception_id = e.object_id
|
17
|
+
|
18
|
+
# Log backtrace in reverse order for easier digestion.
|
19
|
+
if e.backtrace
|
20
|
+
e.backtrace.reverse.each do |backtrace|
|
21
|
+
log_to_stream(stderr, merge_log_contexts(
|
22
|
+
exception_id: exception_id,
|
23
|
+
backtrace: backtrace
|
24
|
+
))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# then log the exception message last so that it's as close to the end of
|
29
|
+
# a log trace as possible
|
30
|
+
data.merge!(
|
31
|
+
exception: true,
|
32
|
+
class: e.class.name,
|
33
|
+
message: e.message,
|
34
|
+
exception_id: exception_id
|
35
|
+
)
|
36
|
+
|
37
|
+
data[:status] = e.status if e.respond_to?(:status)
|
38
|
+
|
39
|
+
log_to_stream(stderr, merge_log_contexts(data))
|
40
|
+
end
|
41
|
+
|
42
|
+
def log_context(data, &block)
|
43
|
+
old = local_context
|
44
|
+
self.local_context = old.merge(data)
|
45
|
+
res = block.call
|
46
|
+
ensure
|
47
|
+
self.local_context = old
|
48
|
+
res
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_context=(default_context)
|
52
|
+
@@default_context = default_context
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_context
|
56
|
+
@@default_context ||= {}
|
57
|
+
end
|
58
|
+
|
59
|
+
def stdout=(stream)
|
60
|
+
@@stdout = stream
|
61
|
+
end
|
62
|
+
|
63
|
+
def stdout
|
64
|
+
@@stdout ||= $stdout
|
65
|
+
end
|
66
|
+
|
67
|
+
def stderr=(stream)
|
68
|
+
@@stderr = stream
|
69
|
+
end
|
70
|
+
|
71
|
+
def stderr
|
72
|
+
@@stderr ||= $stderr
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def merge_log_contexts(data)
|
77
|
+
default_context.merge(request_context.merge(local_context.merge(data)))
|
78
|
+
end
|
79
|
+
|
80
|
+
def local_context
|
81
|
+
RequestStore.store[:local_context] ||= {}
|
82
|
+
end
|
83
|
+
|
84
|
+
def local_context=(h)
|
85
|
+
RequestStore.store[:local_context] = h
|
86
|
+
end
|
87
|
+
|
88
|
+
def request_context
|
89
|
+
RequestStore.store[:request_context] || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
def log_to_stream(stream, data, &block)
|
93
|
+
unless block
|
94
|
+
str = unparse(data)
|
95
|
+
stream.print(str + "\n")
|
96
|
+
else
|
97
|
+
data = data.dup
|
98
|
+
start = Time.now
|
99
|
+
log_to_stream(stream, data.merge(at: 'start'))
|
100
|
+
begin
|
101
|
+
res = yield
|
102
|
+
|
103
|
+
log_to_stream(stream, data.merge(
|
104
|
+
at: 'finish', elapsed: (Time.now - start).to_f))
|
105
|
+
res
|
106
|
+
rescue
|
107
|
+
log_to_stream(stream, data.merge(
|
108
|
+
at: 'exception', elapsed: (Time.now - start).to_f))
|
109
|
+
raise $!
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def unparse(attrs)
|
115
|
+
attrs.map { |k, v| unparse_pair(k, v) }.compact.join(" ")
|
116
|
+
end
|
117
|
+
|
118
|
+
def unparse_pair(k, v)
|
119
|
+
v = v.call if v.is_a?(Proc)
|
120
|
+
# only quote strings if they include whitespace
|
121
|
+
if v == nil
|
122
|
+
nil
|
123
|
+
elsif v == true
|
124
|
+
k
|
125
|
+
elsif v.is_a?(Float)
|
126
|
+
"#{k}=#{format("%.3f", v)}"
|
127
|
+
elsif v.is_a?(String) && v =~ /\s/
|
128
|
+
quote_string(k, v)
|
129
|
+
elsif v.is_a?(Time)
|
130
|
+
"#{k}=#{v.iso8601}"
|
131
|
+
else
|
132
|
+
"#{k}=#{v}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def quote_string(k, v)
|
137
|
+
# try to find a quote style that fits
|
138
|
+
if !v.include?('"')
|
139
|
+
%{#{k}="#{v}"}
|
140
|
+
elsif !v.include?("'")
|
141
|
+
%{#{k}='#{v}'}
|
142
|
+
else
|
143
|
+
%{#{k}="#{v.gsub(/"/, '\\"')}"}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'loggerator'
|
2
|
+
|
3
|
+
module Loggerator
|
4
|
+
module Metrics
|
5
|
+
include Loggerator
|
6
|
+
extend self
|
7
|
+
|
8
|
+
@@metrics_name = 'loggerator'
|
9
|
+
|
10
|
+
def name=(name)
|
11
|
+
@@metrics_name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
@@metrics_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def count(key, value=1)
|
19
|
+
log("count##{name}.#{key}" => value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def sample(key, value)
|
23
|
+
log("sample##{name}.#{key}" => value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def unique(key, value)
|
27
|
+
log("unique##{name}.#{key}" => value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def measure(key, value, units='s')
|
31
|
+
log("measure##{name}.#{key}" => "#{value}#{units}")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
# included Metrics shortcut
|
37
|
+
def m; Metrics; end
|
38
|
+
end
|
39
|
+
|
40
|
+
# simple alias if its not already being used
|
41
|
+
Metrics = Loggerator::Metrics unless defined?(Metrics)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Loggerator::Middleware
|
2
|
+
class RequestID
|
3
|
+
# note that this pattern supports either a full UUID, or a "squashed" UUID
|
4
|
+
# like the kind Hermes sends:
|
5
|
+
#
|
6
|
+
# full: 01234567-89ab-cdef-0123-456789abcdef
|
7
|
+
# squashed: 0123456789abcdef0123456789abcdef
|
8
|
+
#
|
9
|
+
UUID_PATTERN =
|
10
|
+
/\A[a-f0-9]{8}-?[a-f0-9]{4}-?[a-f0-9]{4}-?[a-f0-9]{4}-?[a-f0-9]{12}\Z/
|
11
|
+
|
12
|
+
def initialize(app)
|
13
|
+
@app = app
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
request_ids = [SecureRandom.uuid] + extract_request_ids(env)
|
18
|
+
|
19
|
+
# make ID of the request accessible to consumers down the stack
|
20
|
+
env["REQUEST_ID"] = request_ids[0]
|
21
|
+
|
22
|
+
# Extract request IDs from incoming headers as well. Can be used for
|
23
|
+
# identifying a request across a number of components in SOA.
|
24
|
+
env["REQUEST_IDS"] = request_ids
|
25
|
+
|
26
|
+
status, headers, response = @app.call(env)
|
27
|
+
|
28
|
+
# tag all responses with a request ID
|
29
|
+
headers["Request-Id"] = request_ids[0]
|
30
|
+
|
31
|
+
[status, headers, response]
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def extract_request_ids(env)
|
36
|
+
request_ids = raw_request_ids(env)
|
37
|
+
request_ids.map! { |id| id.strip }
|
38
|
+
request_ids.select! { |id| id =~ UUID_PATTERN }
|
39
|
+
request_ids
|
40
|
+
end
|
41
|
+
|
42
|
+
def raw_request_ids(env)
|
43
|
+
# We had a little disagreement around the inception of the Request-Id
|
44
|
+
# field as to whether it should be prefixed with `X-` or not. API went
|
45
|
+
# with no prefix, but Hermes went with one. Support both formats on
|
46
|
+
# input.
|
47
|
+
%w(HTTP_REQUEST_ID HTTP_X_REQUEST_ID).inject([]) do |request_ids, key|
|
48
|
+
if ids = env[key]
|
49
|
+
request_ids += ids.split(",")
|
50
|
+
end
|
51
|
+
request_ids
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'loggerator'
|
2
|
+
|
3
|
+
module Loggerator
|
4
|
+
module Namespace
|
5
|
+
include Loggerator
|
6
|
+
|
7
|
+
def log(data={}, &blk)
|
8
|
+
log_namespace!
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def log_error(e, data={})
|
13
|
+
log_namespace!
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def log_namespace!
|
19
|
+
self.local_context = { ns: self.class.name }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "loggerator"
|
2
|
+
|
3
|
+
module Loggerator
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
|
6
|
+
config.before_configuration do
|
7
|
+
Rails.application.middleware.insert_after ActionDispatch::RequestId, Loggerator::Middleware::RequestStore
|
8
|
+
Rails.application.middleware.swap ActionDispatch::RequestId, Loggerator::Middleware::RequestID
|
9
|
+
end
|
10
|
+
|
11
|
+
config.before_initialize do
|
12
|
+
[ ActionView::Base,
|
13
|
+
ActiveRecord::Base,
|
14
|
+
ActionMailer::Base,
|
15
|
+
ActionController::Base ].each do |c|
|
16
|
+
|
17
|
+
c.include Loggerator
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Loggerator
|
2
|
+
module RequestStore
|
3
|
+
class << self
|
4
|
+
def clear!
|
5
|
+
Thread.current[:request_store] = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def seed(env)
|
9
|
+
store[:request_id] =
|
10
|
+
env["REQUEST_IDS"] ? env["REQUEST_IDS"].join(",") : nil
|
11
|
+
|
12
|
+
# a global context that evolves over the lifetime of the request, and is
|
13
|
+
# used to tag all log messages that it produces
|
14
|
+
store[:request_context] = {
|
15
|
+
request_id: store[:request_id]
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def store
|
20
|
+
Thread.current[:request_store] ||= {}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Loggerator
|
2
|
+
alias_method :log_on, :log
|
3
|
+
alias_method :log_error_on, :log_error
|
4
|
+
|
5
|
+
def log_off(data, &block)
|
6
|
+
block.call if block
|
7
|
+
end
|
8
|
+
|
9
|
+
def log_error_off(e, data={}, &block)
|
10
|
+
block.call if block
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
@@log_switch = true
|
15
|
+
|
16
|
+
def turn_log(on_or_off)
|
17
|
+
return unless %i[on off].include?(on_or_off.to_sym)
|
18
|
+
alias_method :log, :"log_#{on_or_off}"
|
19
|
+
alias_method :log_error, :"log_error_#{on_or_off}"
|
20
|
+
@@log_switch = on_or_off.to_sym == :on
|
21
|
+
end
|
22
|
+
|
23
|
+
def log?
|
24
|
+
@@log_switch
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
unless ENV.has_key?("TEST_LOGS")
|
31
|
+
Loggerator.turn_log(:off)
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
require 'minitest/mock'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
require_relative '../../../lib/loggerator'
|
7
|
+
|
8
|
+
class Loggerator::Middleware::TestRequestID < Minitest::Test
|
9
|
+
include Rack::Test::Methods
|
10
|
+
|
11
|
+
def app
|
12
|
+
Rack::Builder.new do
|
13
|
+
use Rack::Lint
|
14
|
+
use Loggerator::Middleware::RequestID
|
15
|
+
|
16
|
+
run ->(env) { [ 200, { }, [ 'hi' ] ] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_sets_request_id
|
21
|
+
get '/'
|
22
|
+
|
23
|
+
assert_match ::Loggerator::Middleware::RequestID::UUID_PATTERN,
|
24
|
+
last_request.env['REQUEST_ID']
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_sets_request_ids
|
28
|
+
get '/'
|
29
|
+
|
30
|
+
assert_match ::Loggerator::Middleware::RequestID::UUID_PATTERN,
|
31
|
+
last_request.env['REQUEST_IDS'].first
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
require 'minitest/mock'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
require_relative '../../../lib/loggerator'
|
7
|
+
|
8
|
+
class Loggerator::Middleware::TestRequestStore < Minitest::Test
|
9
|
+
include Rack::Test::Methods
|
10
|
+
|
11
|
+
def app
|
12
|
+
Rack::Builder.new do
|
13
|
+
use Rack::Lint
|
14
|
+
use Loggerator::Middleware::RequestStore
|
15
|
+
|
16
|
+
run ->(env) { [ 200, { }, [ 'hi' ] ] }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_clears_the_store
|
21
|
+
Thread.current[:request_store] = { something_added_before: 'bar' }
|
22
|
+
|
23
|
+
get '/'
|
24
|
+
|
25
|
+
assert_nil Thread.current[:request_store][:something_added_before]
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_seeds_the_store
|
29
|
+
Thread.current[:request_store] = {}
|
30
|
+
|
31
|
+
get '/'
|
32
|
+
|
33
|
+
assert_equal Thread.current[:request_store], {
|
34
|
+
request_id: nil,
|
35
|
+
request_context: {
|
36
|
+
request_id: nil
|
37
|
+
}
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require_relative '../../lib/loggerator'
|
5
|
+
|
6
|
+
class Loggerator::TestRequestStore < Minitest::Test
|
7
|
+
def setup
|
8
|
+
# flush request store
|
9
|
+
Thread.current[:request_store] = {}
|
10
|
+
|
11
|
+
@env = {
|
12
|
+
'REQUEST_ID' => 'abc',
|
13
|
+
'REQUEST_IDS' => %w[ abc def ]
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_seeds_request_id
|
18
|
+
Loggerator::RequestStore.seed(@env)
|
19
|
+
|
20
|
+
assert_equal 'abc,def', Loggerator::RequestStore.store[:request_id]
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_seeds_request_context
|
24
|
+
Loggerator::RequestStore.seed(@env)
|
25
|
+
|
26
|
+
assert_equal 'abc,def', Loggerator::RequestStore.store[:request_context][:request_id]
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_is_cleared_by_clear!
|
30
|
+
Loggerator::RequestStore.seed(@env)
|
31
|
+
Loggerator::RequestStore.clear!
|
32
|
+
|
33
|
+
assert_nil Loggerator::RequestStore.store[:request_id]
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
require_relative '../lib/loggerator'
|
5
|
+
|
6
|
+
class TestLoggerator < Minitest::Test
|
7
|
+
include Loggerator
|
8
|
+
|
9
|
+
def setup
|
10
|
+
# flush request store
|
11
|
+
Thread.current[:request_store] = {}
|
12
|
+
|
13
|
+
self.default_context = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_logs_in_structured_format
|
17
|
+
out, err = capture_subprocess_io do
|
18
|
+
log(foo: "bar", baz: 42)
|
19
|
+
end
|
20
|
+
|
21
|
+
assert_equal out, "foo=bar baz=42\n"
|
22
|
+
assert_equal err, ''
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_re_raises_errors
|
26
|
+
assert_raises(RuntimeError) do
|
27
|
+
capture_subprocess_io do
|
28
|
+
log(foo: 'bar') { raise RuntimeError }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_supports_blocks_to_log_stages_and_elapsed
|
34
|
+
out, _ = capture_subprocess_io do
|
35
|
+
log(foo: 'bar') { }
|
36
|
+
end
|
37
|
+
|
38
|
+
assert_equal out, "foo=bar at=start\n" \
|
39
|
+
+ "foo=bar at=finish elapsed=0.000\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_merges_default_context_with_eq
|
43
|
+
# testing both methods
|
44
|
+
self.default_context = { app: 'my_app' }
|
45
|
+
|
46
|
+
out, _ = capture_subprocess_io do
|
47
|
+
log(foo: 'bar')
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_equal out, "app=my_app foo=bar\n"
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_suports_a_log_context
|
54
|
+
out, _ = capture_subprocess_io do
|
55
|
+
self.log_context(app: 'my_app') do
|
56
|
+
log(foo: 'bar')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
assert_equal out, "app=my_app foo=bar\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_log_context_merged_with_default_context
|
64
|
+
out, _ = capture_subprocess_io do
|
65
|
+
self.default_context = { app: 'my_app' }
|
66
|
+
self.log_context(foo: 'bar') do
|
67
|
+
log(bah: 'boo')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
assert_equal out, "app=my_app foo=bar bah=boo\n"
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: loggerator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Mervine
|
8
|
+
- Reid MacDonald
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-08-23 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Simple web application extension for logging, following the 12factor
|
15
|
+
pattern.
|
16
|
+
email:
|
17
|
+
- joshua@mervine.net
|
18
|
+
- reidmix@gmail.com
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- lib/generators/loggerator/log_generator.rb
|
24
|
+
- lib/generators/templates/log.rb.erb
|
25
|
+
- lib/loggerator.rb
|
26
|
+
- lib/loggerator/loggerator.rb
|
27
|
+
- lib/loggerator/metrics.rb
|
28
|
+
- lib/loggerator/middleware.rb
|
29
|
+
- lib/loggerator/middleware/request_id.rb
|
30
|
+
- lib/loggerator/middleware/request_store.rb
|
31
|
+
- lib/loggerator/namespace.rb
|
32
|
+
- lib/loggerator/rails.rb
|
33
|
+
- lib/loggerator/request_store.rb
|
34
|
+
- lib/loggerator/test.rb
|
35
|
+
- test/loggerator/middleware/request_id_test.rb
|
36
|
+
- test/loggerator/middleware/request_store_test.rb
|
37
|
+
- test/loggerator/request_store_test.rb
|
38
|
+
- test/loggerator_test.rb
|
39
|
+
homepage: https://github.com/heroku/loggerator
|
40
|
+
licenses:
|
41
|
+
- MIT
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 2.5.1
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: 'loggerator: A Log Helper'
|
63
|
+
test_files:
|
64
|
+
- test/loggerator/middleware/request_id_test.rb
|
65
|
+
- test/loggerator/middleware/request_store_test.rb
|
66
|
+
- test/loggerator/request_store_test.rb
|
67
|
+
- test/loggerator_test.rb
|