imprint 1.1.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +100 -35
- data/lib/imprint.rb +3 -2
- data/lib/imprint/middleware.rb +1 -1
- data/lib/imprint/version.rb +1 -1
- data/test/unit/middleware_test.rb +18 -0
- metadata +4 -4
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Imprint helps track requests across multiple log lines or applications. It consists of a lightweight class and middleware to help set tracing ids.
|
4
4
|
|
5
|
-
It also has a file which can be used to bootstrap default rails logging to embedding the imprint `trace_id` on each line logged.
|
5
|
+
It also has a file which can be used to bootstrap default rails logging to embedding the imprint `trace_id` on each line logged.
|
6
6
|
|
7
7
|
Supporting tracing between applications requires updating client calls between applications, at the moment we don't try to monkey patch any of that in and expect responsible clients to add the header manually as described in the Usage section below.
|
8
8
|
|
@@ -10,55 +10,65 @@ Supporting tracing between applications requires updating client calls between a
|
|
10
10
|
|
11
11
|
Add this line to your application's Gemfile:
|
12
12
|
|
13
|
-
|
13
|
+
```ruby
|
14
|
+
gem 'imprint'
|
15
|
+
```
|
14
16
|
|
15
17
|
And then execute:
|
16
18
|
|
17
|
-
|
19
|
+
```bash
|
20
|
+
$ bundle
|
21
|
+
```
|
18
22
|
|
19
23
|
Or install it yourself as:
|
20
24
|
|
21
|
-
|
22
|
-
|
25
|
+
```bash
|
26
|
+
$ gem install imprint
|
27
|
+
```
|
23
28
|
|
24
29
|
## Usage
|
25
30
|
|
26
31
|
After installing the gems and requiring them if needed.
|
27
32
|
|
28
|
-
To configure in a Rails 3 or 4 application
|
33
|
+
To configure in a Rails 2, 3, or 4 application
|
29
34
|
|
30
35
|
edit `config/application.rb` and append the line below
|
31
36
|
|
32
|
-
|
33
|
-
|
37
|
+
```ruby
|
38
|
+
require 'imprint/rails_logger'
|
39
|
+
```
|
40
|
+
|
34
41
|
create or update your middleware configuration (for example: `config/initializers/middleware.rb`)
|
35
42
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
```ruby
|
44
|
+
require 'imprint'
|
45
|
+
|
46
|
+
Rails.application.config.middleware.insert_before Rails::Rack::Logger, Imprint::Middleware
|
47
|
+
```
|
48
|
+
|
42
49
|
If you are using any additional loggers that you wanted tagged that are not part of the normal Rails.logger you should update them as well. For example, we have some scribe logs:
|
43
50
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
51
|
+
```ruby
|
52
|
+
def log(message = nil, severity = :info)
|
53
|
+
mirror_logger.add(parse_severity(severity), message) if mirror_logger
|
54
|
+
log_raw(message, severity) do
|
55
|
+
message = yield if block_given?
|
56
|
+
# append imprint trace
|
57
|
+
if (defined?(Imprint::Tracer.get_trace_id)) && message && message.is_a?(String) && message.length > 1 && Imprint::Tracer.get_trace_id.get_trace_id
|
58
|
+
message = "#{message}\n" unless message[-1] == "\n"
|
59
|
+
message = message.gsub("\n"," [trace_id=#{Imprint::Middleware.get_trace_id}]\n")
|
60
|
+
end
|
61
|
+
format = []
|
62
|
+
format << Time.now.to_f
|
63
|
+
format << @host
|
64
|
+
format << $$
|
65
|
+
format << format_severity(severity)
|
66
|
+
format << "app_name"
|
67
|
+
format << message
|
68
|
+
format.flatten.join("\t")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
62
72
|
|
63
73
|
## Example Queries
|
64
74
|
|
@@ -77,9 +87,64 @@ Find all log lines in a particular app related to a single request:
|
|
77
87
|
Find all long lines related to a single request across apps:
|
78
88
|
|
79
89
|
"trace_id=1396448370_wdeYND"
|
80
|
-
|
90
|
+
|
81
91
|
Since the trace_id is appended to all log lines during the duration of the request, any `logger.info`, `logger.error`, or other log output is easy to track back to the initial request information, params, headers, or other system logged information such as if the request was successfully authorize and by whom.
|
82
92
|
|
93
|
+
## Background Job Support
|
94
|
+
|
95
|
+
We have a gateway wrapped about our Resque enqueue call. At this point I inject the trace_id. This makes it easy to ensure the job is queue with the params. So all failed jobs will include the trace_id
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
options[:trace_id] ||= if (defined?(Imprint::Tracer)) && Imprint::Tracer.get_trace_id
|
99
|
+
Imprint::Tracer.get_trace_id
|
100
|
+
else
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
Resque.enqueue(klazz, options)
|
105
|
+
```
|
106
|
+
|
107
|
+
Once it is on the queue, I want to log the ID but remove it from the params as some jobs work direclty with an expected set of params.
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
def before_perform(*args)
|
111
|
+
pluck_imprint_id
|
112
|
+
#any other before filters
|
113
|
+
end
|
114
|
+
|
115
|
+
def pluck_imprint_id
|
116
|
+
if defined?(Imprint::Tracer)
|
117
|
+
existing_id = params.delete(:trace_id)
|
118
|
+
Imprint::Tracer.set_trace_id(existing_id, {}) if existing_id
|
119
|
+
true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
The process of adding support to other background processing should be pretty similar.
|
125
|
+
|
126
|
+
## Internal API Request Tracing (cross app tracing)
|
127
|
+
|
128
|
+
If you want to trace requests that go across multiple applications Imprint can help you out here as well. Basically the middleware only generates a new trace_id if the incoming requests don't have a special Imprint header `HTTP_IMPRINTID`
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
existing_id = rack_env[Imprint::Tracer::TRACER_HEADER]
|
132
|
+
existing_id ||= "#{Time.now.to_i}_#{Imprint::Tracer.rand_trace_id}"
|
133
|
+
Imprint::Tracer.set_trace_id(existing_id, rack_env)
|
134
|
+
```
|
135
|
+
|
136
|
+
To trace any requests made by a external facing app to internal APIs just inject the current `trace_id` into the header of the api request. Here is an example from a client gem. First we isolated all the requests to a single gem request gateway method `http_get`. Then in this example we are using `RestClient` so we just add the header to the outgoing request.
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
def self.http_get(url)
|
140
|
+
if defined?(Imprint::Tracer) && Imprint::Tracer.get_trace_id
|
141
|
+
RestClient.get(url, { Imprint::Tracer::TRACER_KEY => Imprint::Tracer.get_trace_id})
|
142
|
+
else
|
143
|
+
RestClient.get(url)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
83
148
|
## Contributing
|
84
149
|
|
85
150
|
1. Fork it
|
@@ -88,6 +153,6 @@ Since the trace_id is appended to all log lines during the duration of the reque
|
|
88
153
|
4. Push to the branch (`git push origin my-new-feature`)
|
89
154
|
5. Create new Pull Request
|
90
155
|
|
91
|
-
## License
|
156
|
+
## License
|
92
157
|
|
93
|
-
See LICENSE.txt for details.
|
158
|
+
See LICENSE.txt for details.
|
data/lib/imprint.rb
CHANGED
@@ -3,8 +3,9 @@ require 'imprint/middleware'
|
|
3
3
|
|
4
4
|
module Imprint
|
5
5
|
class Tracer
|
6
|
-
TRACER_HEADER
|
7
|
-
TRACER_KEY
|
6
|
+
TRACER_HEADER = 'HTTP_IMPRINTID'
|
7
|
+
TRACER_KEY = 'IMPRINTID'
|
8
|
+
RAILS_REQUEST_ID = "action_dispatch.request_id"
|
8
9
|
|
9
10
|
TRACE_CHARS = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten
|
10
11
|
|
data/lib/imprint/middleware.rb
CHANGED
@@ -2,7 +2,7 @@ module Imprint
|
|
2
2
|
class Middleware
|
3
3
|
|
4
4
|
def self.set_request_trace_id(rack_env)
|
5
|
-
existing_id = rack_env[Imprint::Tracer::TRACER_HEADER]
|
5
|
+
existing_id = rack_env[Imprint::Tracer::TRACER_HEADER] || rack_env[Imprint::Tracer::RAILS_REQUEST_ID]
|
6
6
|
existing_id ||= "#{Time.now.to_i}_#{Imprint::Tracer.rand_trace_id}"
|
7
7
|
Imprint::Tracer.set_trace_id(existing_id, rack_env)
|
8
8
|
end
|
data/lib/imprint/version.rb
CHANGED
@@ -24,6 +24,24 @@ class MiddlewareTest < Test::Unit::TestCase
|
|
24
24
|
assert ::Imprint::Tracer.get_trace_id!='-1'
|
25
25
|
end
|
26
26
|
|
27
|
+
should "set trace_id from rails request_id" do
|
28
|
+
request = Rack::MockRequest.env_for("/anything.json", {"action_dispatch.request_id" => 'existing_id' })
|
29
|
+
middleware = Imprint::Middleware.new(fake_app)
|
30
|
+
results = middleware.call(request)
|
31
|
+
assert_equal "/anything.json", results.last
|
32
|
+
assert_not_nil ::Imprint::Tracer.get_trace_id
|
33
|
+
assert ::Imprint::Tracer.get_trace_id=='existing_id'
|
34
|
+
end
|
35
|
+
|
36
|
+
should "set trace_id from passed in imprint header" do
|
37
|
+
request = Rack::MockRequest.env_for("/anything.json", {"HTTP_IMPRINTID" => 'existing_trace_id' })
|
38
|
+
middleware = Imprint::Middleware.new(fake_app)
|
39
|
+
results = middleware.call(request)
|
40
|
+
assert_equal "/anything.json", results.last
|
41
|
+
assert_not_nil ::Imprint::Tracer.get_trace_id
|
42
|
+
assert ::Imprint::Tracer.get_trace_id=='existing_trace_id'
|
43
|
+
end
|
44
|
+
|
27
45
|
private
|
28
46
|
|
29
47
|
def fake_app
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imprint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-05-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -144,7 +144,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
144
|
version: '0'
|
145
145
|
segments:
|
146
146
|
- 0
|
147
|
-
hash:
|
147
|
+
hash: -2039852433245629427
|
148
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
149
|
none: false
|
150
150
|
requirements:
|
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
version: '0'
|
154
154
|
segments:
|
155
155
|
- 0
|
156
|
-
hash:
|
156
|
+
hash: -2039852433245629427
|
157
157
|
requirements: []
|
158
158
|
rubyforge_project:
|
159
159
|
rubygems_version: 1.8.23
|