loggerator 0.0.1
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.
- 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
|