logjam_agent 0.30.0 → 0.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +49 -28
- data/Rakefile +5 -0
- data/lib/logjam_agent.rb +7 -3
- data/lib/logjam_agent/active_support/core_ext/array/extract.rb +21 -0
- data/lib/logjam_agent/active_support/parameter_filter.rb +128 -0
- data/lib/logjam_agent/buffered_logger.rb +17 -42
- data/lib/logjam_agent/middleware.rb +15 -3
- data/lib/logjam_agent/rack/logger.rb +19 -81
- data/lib/logjam_agent/rack/rails_support.rb +26 -0
- data/lib/logjam_agent/rack/sinatra_request.rb +32 -0
- data/lib/logjam_agent/railtie.rb +3 -0
- data/lib/logjam_agent/receiver.rb +22 -0
- data/lib/logjam_agent/sinatra.rb +116 -0
- data/lib/logjam_agent/syslog_like_formatter.rb +1 -1
- data/lib/logjam_agent/util.rb +6 -1
- data/lib/logjam_agent/version.rb +1 -1
- data/lib/logjam_agent/zmq_forwarder.rb +8 -2
- data/test/sinatra_app.rb +32 -0
- data/test/sinatra_classic_app.rb +31 -0
- data/test/sinatra_classic_test.rb +20 -0
- data/test/sinatra_test.rb +54 -0
- data/test/test_helper.rb +6 -1
- data/test/util_test.rb +5 -0
- metadata +69 -16
- data/.gitignore +0 -5
- data/Gemfile +0 -4
- data/logjam_agent.gemspec +0 -32
- data/script/console +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b543de9e4f7a8d5ae896a7c2fa4524a8b220a1dad8a6b4e1be6b5eee4c8110e
|
4
|
+
data.tar.gz: 62f2aee617a120107307e625b2ba2df8fb461f53ba9fa3baff0ce0187fc1325f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec3578d040a1033e06029caf81256e6524a66a7c8c24493e986e467a603564e53b22cc05eadf243a3310ccfb8b3b065c012759e5d21d2acd9e64b597e4fb6710
|
7
|
+
data.tar.gz: ed17803ea6301229c58b82e2886cf82bb36fa88554567f5864e0d38df653a2b2a07fe76160b49de55ef03619b745608e95648364532f3f7e465021a558ae7ae1
|
data/README.md
CHANGED
@@ -5,9 +5,14 @@ Client side library for logjam.
|
|
5
5
|
Hooks into Rails, collects log lines, performance metrics, error/exception infomation and Rack
|
6
6
|
environment information and sends this data to [Logjam](https://github.com/skaes/logjam_app).
|
7
7
|
|
8
|
+
Has experimental support for Sinatra.
|
9
|
+
|
8
10
|
Currently only one mechanism is available for data transport:
|
9
11
|
ZeroMQ. Support for AMQP has been dropped.
|
10
12
|
|
13
|
+
[![Travis](https://travis-ci.org/skaes/logjam_agent.svg?branch=master)](https://travis-ci.org/github/skaes/logjam_agent)
|
14
|
+
|
15
|
+
|
11
16
|
## Usage
|
12
17
|
|
13
18
|
For ZeroMQ, add
|
@@ -110,10 +115,8 @@ end
|
|
110
115
|
|
111
116
|
### Generating unique request ids
|
112
117
|
|
113
|
-
The agent generates unique request ids for all request handled
|
114
|
-
|
115
|
-
available in the application. Otherwise it will fall back to use the
|
116
|
-
standard `SecureRandom` class shipped with Ruby.
|
118
|
+
The agent generates unique request ids for all request handled using standard
|
119
|
+
`SecureRandom` class shipped with Ruby.
|
117
120
|
|
118
121
|
### Generating JSON
|
119
122
|
|
@@ -121,38 +124,56 @@ The agent will try to use the [Oj](https://github.com/ohler55/oj) to
|
|
121
124
|
generate JSON. If this is not available in your application, it will
|
122
125
|
fall back to the `to_json` method.
|
123
126
|
|
124
|
-
## Troubleshooting
|
125
127
|
|
126
|
-
|
127
|
-
`logjam_agent_error.log` which you can find under `Rails.root/log`.
|
128
|
-
If you set the `RAILS_LOG_TO_STDOUT` environment variable, those logs will be available through `stderr`.
|
128
|
+
### Sinatra
|
129
129
|
|
130
|
-
|
130
|
+
Supports both classic and modular Sinatra applications. Since Sinatra doesn't have built
|
131
|
+
in action names like Rails, you'll have to declare them in your handlers, or in a before
|
132
|
+
filter. Example:
|
131
133
|
|
132
134
|
```ruby
|
133
|
-
|
135
|
+
require 'logjam_agent/sinatra'
|
136
|
+
|
137
|
+
use LogjamAgent::Sinatra::Middleware
|
138
|
+
|
139
|
+
class SinatraTestApp < Sinatra::Base
|
140
|
+
register LogjamAgent::Sinatra
|
141
|
+
|
142
|
+
configure do
|
143
|
+
set :loglevel, :debug
|
144
|
+
setup_logjam_logger
|
145
|
+
|
146
|
+
LogjamAgent.application_name = "myapp"
|
147
|
+
LogjamAgent.add_forwarder(:zmq, :host => "my-logjam-broker")
|
148
|
+
LogjamAgent.parameter_filters << :password
|
149
|
+
end
|
150
|
+
|
151
|
+
before '/index' do
|
152
|
+
action_name "Simple#index"
|
153
|
+
end
|
154
|
+
|
155
|
+
get '/index' do
|
156
|
+
logger.info 'Hello World!'
|
157
|
+
'Hello World!'
|
158
|
+
end
|
159
|
+
end
|
134
160
|
```
|
135
161
|
|
136
|
-
|
162
|
+
The environment name is picked up from either the environment variable `LOGJAM_ENV`, or
|
163
|
+
Sinatra's environment setting.
|
137
164
|
|
138
|
-
|
165
|
+
Set the environment variable `APP_LOG_TO_STDOUT` if you want to log to `STDOUT`.
|
166
|
+
Otherwise, logs will appear in the subdirectory `log` of your application's root.
|
139
167
|
|
140
|
-
Copyright (c) 2013 - 2019 Stefan Kaes
|
141
168
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
furnished to do so, subject to the following conditions:
|
169
|
+
## Troubleshooting
|
170
|
+
|
171
|
+
If the agent experiences problems when sending data, it will log information to a file named
|
172
|
+
`logjam_agent_error.log` which you can find under `Rails.root/log`.
|
173
|
+
If you set the `RAILS_LOG_TO_STDOUT` environment variable, those logs will be available through `stderr`.
|
148
174
|
|
149
|
-
|
150
|
-
all copies or substantial portions of the Software.
|
175
|
+
This behavior is customizable via a module level call back method:
|
151
176
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
156
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
157
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
158
|
-
THE SOFTWARE.
|
177
|
+
```ruby
|
178
|
+
LogjamAgent.error_handler = lambda {|exception| ... }
|
179
|
+
```
|
data/Rakefile
CHANGED
@@ -7,8 +7,13 @@ Rake::TestTask.new do |t|
|
|
7
7
|
t.libs << "test"
|
8
8
|
t.test_files = FileList['test/**/*_test.rb']
|
9
9
|
t.verbose = true
|
10
|
+
t.ruby_opts = %w(-W1)
|
10
11
|
end
|
11
12
|
|
12
13
|
task :default do
|
13
14
|
Rake::Task[:test].invoke
|
14
15
|
end
|
16
|
+
|
17
|
+
task :integration do
|
18
|
+
sh "cd railsapp && rake"
|
19
|
+
end
|
data/lib/logjam_agent.rb
CHANGED
@@ -36,9 +36,7 @@ require "logjam_agent/request"
|
|
36
36
|
require "logjam_agent/buffered_logger"
|
37
37
|
require "logjam_agent/syslog_like_formatter"
|
38
38
|
|
39
|
-
if defined?(Rails)
|
40
|
-
require "logjam_agent/railtie"
|
41
|
-
end
|
39
|
+
require "logjam_agent/railtie" if defined?(Rails::Railtie)
|
42
40
|
|
43
41
|
# monkey patch log levels to include NONE
|
44
42
|
require 'logger'
|
@@ -74,6 +72,9 @@ module LogjamAgent
|
|
74
72
|
mattr_accessor :action_name_proc
|
75
73
|
self.action_name_proc = lambda{|name| name}
|
76
74
|
|
75
|
+
mattr_accessor :parameter_filters
|
76
|
+
self.parameter_filters = []
|
77
|
+
|
77
78
|
def self.get_hostname
|
78
79
|
n = Socket.gethostname
|
79
80
|
if n.split('.').size > 1
|
@@ -97,6 +98,9 @@ module LogjamAgent
|
|
97
98
|
mattr_accessor :disabled
|
98
99
|
self.disabled = false
|
99
100
|
|
101
|
+
mattr_accessor :ensure_ping_at_exit
|
102
|
+
self.ensure_ping_at_exit = true
|
103
|
+
|
100
104
|
mattr_accessor :obfuscate_ips
|
101
105
|
self.obfuscate_ips = false
|
102
106
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Array
|
4
|
+
# Removes and returns the elements for which the block returns a true value.
|
5
|
+
# If no block is given, an Enumerator is returned instead.
|
6
|
+
#
|
7
|
+
# numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
8
|
+
# odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
|
9
|
+
# numbers # => [0, 2, 4, 6, 8]
|
10
|
+
def extract!
|
11
|
+
return to_enum(:extract!) { size } unless block_given?
|
12
|
+
|
13
|
+
extracted_elements = []
|
14
|
+
|
15
|
+
reject! do |element|
|
16
|
+
extracted_elements << element if yield(element)
|
17
|
+
end
|
18
|
+
|
19
|
+
extracted_elements
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/object/duplicable"
|
4
|
+
require_relative "core_ext/array/extract"
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
# +ParameterFilter+ allows you to specify keys for sensitive data from
|
8
|
+
# hash-like object and replace corresponding value. Filtering only certain
|
9
|
+
# sub-keys from a hash is possible by using the dot notation:
|
10
|
+
# 'credit_card.number'. If a proc is given, each key and value of a hash and
|
11
|
+
# all sub-hashes are passed to it, where the value or the key can be replaced
|
12
|
+
# using String#replace or similar methods.
|
13
|
+
#
|
14
|
+
# ActiveSupport::ParameterFilter.new([:password])
|
15
|
+
# => replaces the value to all keys matching /password/i with "[FILTERED]"
|
16
|
+
#
|
17
|
+
# ActiveSupport::ParameterFilter.new([:foo, "bar"])
|
18
|
+
# => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
19
|
+
#
|
20
|
+
# ActiveSupport::ParameterFilter.new(["credit_card.code"])
|
21
|
+
# => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
|
22
|
+
# change { file: { code: "xxxx"} }
|
23
|
+
#
|
24
|
+
# ActiveSupport::ParameterFilter.new([-> (k, v) do
|
25
|
+
# v.reverse! if k =~ /secret/i
|
26
|
+
# end])
|
27
|
+
# => reverses the value to all keys matching /secret/i
|
28
|
+
class ParameterFilter
|
29
|
+
FILTERED = "[FILTERED]" # :nodoc:
|
30
|
+
|
31
|
+
# Create instance with given filters. Supported type of filters are +String+, +Regexp+, and +Proc+.
|
32
|
+
# Other types of filters are treated as +String+ using +to_s+.
|
33
|
+
# For +Proc+ filters, key, value, and optional original hash is passed to block arguments.
|
34
|
+
#
|
35
|
+
# ==== Options
|
36
|
+
#
|
37
|
+
# * <tt>:mask</tt> - A replaced object when filtered. Defaults to +"[FILTERED]"+
|
38
|
+
def initialize(filters = [], mask: FILTERED)
|
39
|
+
@filters = filters
|
40
|
+
@mask = mask
|
41
|
+
end
|
42
|
+
|
43
|
+
# Mask value of +params+ if key matches one of filters.
|
44
|
+
def filter(params)
|
45
|
+
compiled_filter.call(params)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns filtered value for given key. For +Proc+ filters, third block argument is not populated.
|
49
|
+
def filter_param(key, value)
|
50
|
+
@filters.empty? ? value : compiled_filter.value_for_key(key, value)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def compiled_filter
|
55
|
+
@compiled_filter ||= CompiledFilter.compile(@filters, mask: @mask)
|
56
|
+
end
|
57
|
+
|
58
|
+
class CompiledFilter # :nodoc:
|
59
|
+
def self.compile(filters, mask:)
|
60
|
+
return lambda { |params| params.dup } if filters.empty?
|
61
|
+
|
62
|
+
strings, regexps, blocks = [], [], []
|
63
|
+
|
64
|
+
filters.each do |item|
|
65
|
+
case item
|
66
|
+
when Proc
|
67
|
+
blocks << item
|
68
|
+
when Regexp
|
69
|
+
regexps << item
|
70
|
+
else
|
71
|
+
strings << Regexp.escape(item.to_s)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
deep_regexps = regexps.extract! { |r| r.to_s.include?("\\.") }
|
76
|
+
deep_strings = strings.extract! { |s| s.include?("\\.") }
|
77
|
+
|
78
|
+
regexps << Regexp.new(strings.join("|"), true) unless strings.empty?
|
79
|
+
deep_regexps << Regexp.new(deep_strings.join("|"), true) unless deep_strings.empty?
|
80
|
+
|
81
|
+
new regexps, deep_regexps, blocks, mask: mask
|
82
|
+
end
|
83
|
+
|
84
|
+
attr_reader :regexps, :deep_regexps, :blocks
|
85
|
+
|
86
|
+
def initialize(regexps, deep_regexps, blocks, mask:)
|
87
|
+
@regexps = regexps
|
88
|
+
@deep_regexps = deep_regexps.any? ? deep_regexps : nil
|
89
|
+
@blocks = blocks
|
90
|
+
@mask = mask
|
91
|
+
end
|
92
|
+
|
93
|
+
def call(params, parents = [], original_params = params)
|
94
|
+
filtered_params = params.class.new
|
95
|
+
|
96
|
+
params.each do |key, value|
|
97
|
+
filtered_params[key] = value_for_key(key, value, parents, original_params)
|
98
|
+
end
|
99
|
+
|
100
|
+
filtered_params
|
101
|
+
end
|
102
|
+
|
103
|
+
def value_for_key(key, value, parents = [], original_params = nil)
|
104
|
+
parents.push(key) if deep_regexps
|
105
|
+
if regexps.any? { |r| r.match?(key.to_s) }
|
106
|
+
value = @mask
|
107
|
+
elsif deep_regexps && (joined = parents.join(".")) && deep_regexps.any? { |r| r.match?(joined) }
|
108
|
+
value = @mask
|
109
|
+
elsif value.is_a?(Hash)
|
110
|
+
value = call(value, parents, original_params)
|
111
|
+
elsif value.is_a?(Array)
|
112
|
+
# If we don't pop the current parent it will be duplicated as we
|
113
|
+
# process each array value.
|
114
|
+
parents.pop if deep_regexps
|
115
|
+
value = value.map { |v| value_for_key(key, v, parents, original_params) }
|
116
|
+
# Restore the parent stack after processing the array.
|
117
|
+
parents.push(key) if deep_regexps
|
118
|
+
elsif blocks.any?
|
119
|
+
key = key.dup if key.duplicable?
|
120
|
+
value = value.dup if value.duplicable?
|
121
|
+
blocks.each { |b| b.arity == 2 ? b.call(key, value) : b.call(key, value, original_params) }
|
122
|
+
end
|
123
|
+
parents.pop if deep_regexps
|
124
|
+
value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -1,54 +1,31 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
|
3
|
-
|
4
|
-
require 'active_support/buffered_logger'
|
5
|
-
require 'active_support/core_ext/logger'
|
6
|
-
if ActiveSupport::VERSION::STRING >= "3.2"
|
7
|
-
require 'active_support/tagged_logging'
|
8
|
-
# monkey patch to handle exceptions correctly
|
9
|
-
# not needed for rails 4 as this uses a Formatter to add the tags
|
10
|
-
class ActiveSupport::TaggedLogging
|
11
|
-
def initialize(logger)
|
12
|
-
@logger = logger
|
13
|
-
if logger.is_a?(LogjamAgent::BufferedLogger)
|
14
|
-
self.class.class_eval <<-EVAL, __FILE__, __LINE__ + 1
|
15
|
-
def add(severity, message = nil, progname = nil, &block)
|
16
|
-
@logger.add(severity, message, progname, tags_text, &block)
|
17
|
-
end
|
18
|
-
EVAL
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
else
|
24
|
-
require 'active_support/logger'
|
3
|
+
require 'active_support/logger'
|
25
4
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
5
|
+
class LogjamAgent::ConsoleFormatter < Logger::Formatter
|
6
|
+
# This method is invoked when a log event occurs
|
7
|
+
def call(severity, timestamp, progname, msg)
|
8
|
+
"[#{format_time(timestamp)}] #{String === msg ? msg : msg.inspect}\n"
|
9
|
+
end
|
31
10
|
|
32
|
-
|
33
|
-
|
34
|
-
end
|
11
|
+
def format_time(timestamp)
|
12
|
+
timestamp.strftime("%H:%M:%S.#{"%06d" % timestamp.usec}")
|
35
13
|
end
|
14
|
+
end
|
36
15
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
16
|
+
class ActiveSupport::Logger
|
17
|
+
class << self
|
18
|
+
alias_method :original_broadcast, :broadcast
|
19
|
+
def broadcast(logger)
|
20
|
+
logger.formatter = LogjamAgent::ConsoleFormatter.new
|
21
|
+
logger.formatter.extend(ActiveSupport::TaggedLogging::Formatter)
|
22
|
+
original_broadcast(logger)
|
45
23
|
end
|
46
24
|
end
|
47
25
|
end
|
48
26
|
|
49
27
|
module LogjamAgent
|
50
|
-
class BufferedLogger <
|
51
|
-
ActiveSupport::BufferedLogger : ActiveSupport::Logger )
|
28
|
+
class BufferedLogger < ActiveSupport::Logger
|
52
29
|
|
53
30
|
attr_accessor :formatter
|
54
31
|
|
@@ -57,8 +34,6 @@ module LogjamAgent
|
|
57
34
|
|
58
35
|
def initialize(*args)
|
59
36
|
super(*args)
|
60
|
-
# stupid bug in the buffered logger code (Rails::VERSION::STRING < "3.2")
|
61
|
-
@log.write "\n" if @log && respond_to?(:buffer)
|
62
37
|
@formatter = lambda{|_, _, _, message| message}
|
63
38
|
end
|
64
39
|
|
@@ -1,11 +1,16 @@
|
|
1
1
|
module LogjamAgent
|
2
2
|
class Middleware
|
3
|
-
def initialize(app,
|
3
|
+
def initialize(app, framework = :rails)
|
4
4
|
@app = app
|
5
|
-
@
|
5
|
+
@framework = framework
|
6
|
+
unless %i{rails sinatra}.include?(framework)
|
7
|
+
raise ArgumentError.new("Invalid logjam_agent framework: #{framework}. Only :rails and :sinatra are valid!")
|
8
|
+
end
|
9
|
+
@reraise = defined?(Rails::Railtie) && Rails.env.test?
|
6
10
|
end
|
7
11
|
|
8
12
|
def call(env)
|
13
|
+
env["logjam_agent.framework"] = @framework
|
9
14
|
strip_encoding_from_etag(env)
|
10
15
|
request = start_request(env)
|
11
16
|
result = @app.call(env)
|
@@ -13,9 +18,13 @@ module LogjamAgent
|
|
13
18
|
result
|
14
19
|
rescue Exception
|
15
20
|
result = [500, {'Content-Type' => 'text/html'}, ["<html><body><h1>500 Internal Server Error</h1></body></html>"]]
|
21
|
+
raise if @reraise
|
16
22
|
ensure
|
17
23
|
headers = result[1]
|
18
24
|
headers["X-Logjam-Request-Id"] = request.id
|
25
|
+
if env["sinatra.static_file"]
|
26
|
+
request.fields[:action] = "Sinatra#static_file"
|
27
|
+
end
|
19
28
|
unless (request_action = request.fields[:action]).blank?
|
20
29
|
headers["X-Logjam-Request-Action"] = request_action
|
21
30
|
end
|
@@ -41,7 +50,10 @@ module LogjamAgent
|
|
41
50
|
env_name = env["logjam_agent.environment_name"] || LogjamAgent.environment_name
|
42
51
|
caller_id = env["HTTP_X_LOGJAM_CALLER_ID"] || ""
|
43
52
|
caller_action = env["HTTP_X_LOGJAM_ACTION"] || ""
|
44
|
-
|
53
|
+
extra_fields = {}
|
54
|
+
extra_fields[:caller_id] = caller_id if caller_id.present?
|
55
|
+
extra_fields[:caller_action] = caller_action if caller_action.present?
|
56
|
+
LogjamAgent.start_request(app_name, env_name, extra_fields)
|
45
57
|
end
|
46
58
|
|
47
59
|
def finish_request(env)
|
@@ -7,14 +7,19 @@ module LogjamAgent
|
|
7
7
|
class Logger < ActiveSupport::LogSubscriber
|
8
8
|
def initialize(app, taggers = nil)
|
9
9
|
@app = app
|
10
|
-
@taggers = taggers || Rails.application.config.log_tags || []
|
10
|
+
@taggers = taggers || (defined?(Rails::Railtie) ? Rails.application.config.log_tags : []) || []
|
11
11
|
@hostname = LogjamAgent.hostname
|
12
12
|
@asset_prefix = Rails.application.config.assets.prefix rescue "---"
|
13
13
|
@ignore_asset_requests = LogjamAgent.ignore_asset_requests
|
14
14
|
end
|
15
15
|
|
16
16
|
def call(env)
|
17
|
-
|
17
|
+
if env["logjam_agent.framework"] == :sinatra
|
18
|
+
request = ::Sinatra::Request.new(env)
|
19
|
+
env["rack.logger"] = logger
|
20
|
+
else
|
21
|
+
request = ActionDispatch::Request.new(env)
|
22
|
+
end
|
18
23
|
|
19
24
|
if logger.respond_to?(:tagged) && !@taggers.empty?
|
20
25
|
logger.tagged(compute_tags(request)) { call_app(request, env) }
|
@@ -88,7 +93,7 @@ module LogjamAgent
|
|
88
93
|
spoofed = nil
|
89
94
|
ip = nil
|
90
95
|
begin
|
91
|
-
ip = LogjamAgent.ip_obfuscator(env["action_dispatch.remote_ip"].to_s)
|
96
|
+
ip = LogjamAgent.ip_obfuscator((env["action_dispatch.remote_ip"] || request.ip).to_s)
|
92
97
|
rescue ActionDispatch::RemoteIp::IpSpoofAttackError => spoofed
|
93
98
|
ip = "*** SPOOFED IP ***"
|
94
99
|
end
|
@@ -107,6 +112,11 @@ module LogjamAgent
|
|
107
112
|
if completed_info = Thread.current.thread_variable_get(:time_bandits_completed_info)
|
108
113
|
_, additions, view_time, _ = completed_info
|
109
114
|
end
|
115
|
+
additions ||= []
|
116
|
+
if env["logjam_agent.framework"] == :sinatra
|
117
|
+
TimeBandits.consumed
|
118
|
+
additions.concat TimeBandits.runtimes
|
119
|
+
end
|
110
120
|
logjam_request = LogjamAgent.request
|
111
121
|
|
112
122
|
if (allowed_time_ms = env['HTTP_X_LOGJAM_CALLER_TIMEOUT'].to_i) > 0 && (run_time_ms > allowed_time_ms)
|
@@ -123,9 +133,9 @@ module LogjamAgent
|
|
123
133
|
info message unless logjam_request.ignored?
|
124
134
|
|
125
135
|
ActiveSupport::LogSubscriber.flush_all!
|
126
|
-
request_info = {
|
127
|
-
|
128
|
-
|
136
|
+
request_info = { :total_time => run_time_ms, :code => status }
|
137
|
+
request_info[:view_time] = view_time if view_time
|
138
|
+
request_info[:wait_time] = wait_time_ms if wait_time_ms > 0
|
129
139
|
logjam_request.fields.merge!(request_info)
|
130
140
|
|
131
141
|
env["time_bandits.metrics"] = TimeBandits.metrics
|
@@ -153,7 +163,7 @@ module LogjamAgent
|
|
153
163
|
|
154
164
|
result
|
155
165
|
rescue Exception => e
|
156
|
-
|
166
|
+
logger.error(e)
|
157
167
|
result
|
158
168
|
end
|
159
169
|
|
@@ -197,82 +207,10 @@ module LogjamAgent
|
|
197
207
|
|
198
208
|
headers
|
199
209
|
end
|
200
|
-
|
201
210
|
end
|
202
211
|
end
|
203
212
|
end
|
204
213
|
|
205
|
-
|
206
|
-
|
207
|
-
require 'action_controller/log_subscriber'
|
208
|
-
|
209
|
-
module ActionController #:nodoc:
|
210
|
-
|
211
|
-
class LogSubscriber
|
212
|
-
if Rails::VERSION::STRING =~ /\A3\.0/
|
213
|
-
def start_processing(event)
|
214
|
-
payload = event.payload
|
215
|
-
params = payload[:params].except(*INTERNAL_PARAMS)
|
216
|
-
|
217
|
-
controller = payload[:controller]
|
218
|
-
action = payload[:action]
|
219
|
-
full_name = "#{controller}##{action}"
|
220
|
-
action_name = LogjamAgent.action_name_proc.call(full_name)
|
221
|
-
|
222
|
-
LogjamAgent.request.fields[:action] = action_name
|
223
|
-
|
224
|
-
info " Processing by #{full_name} as #{payload[:formats].first.to_s.upcase}"
|
225
|
-
info " Parameters: #{params.inspect}" unless params.empty?
|
226
|
-
end
|
227
|
-
|
228
|
-
elsif Rails::VERSION::STRING =~ /\A3\.1/
|
229
|
-
|
230
|
-
def start_processing(event)
|
231
|
-
payload = event.payload
|
232
|
-
params = payload[:params].except(*INTERNAL_PARAMS)
|
233
|
-
format = payload[:format]
|
234
|
-
format = format.to_s.upcase if format.is_a?(Symbol)
|
235
|
-
|
236
|
-
controller = payload[:controller]
|
237
|
-
action = payload[:action]
|
238
|
-
full_name = "#{controller}##{action}"
|
239
|
-
action_name = LogjamAgent.action_name_proc.call(full_name)
|
240
|
-
|
241
|
-
LogjamAgent.request.fields[:action] = action_name
|
242
|
-
|
243
|
-
info " Processing by #{full_name} as #{format}"
|
244
|
-
info " Parameters: #{params.inspect}" unless params.empty?
|
245
|
-
end
|
246
|
-
|
247
|
-
elsif Rails::VERSION::STRING =~ /\A(3\.2|4|5|6)/
|
248
|
-
|
249
|
-
# Rails 4.1 uses method_added to automatically subscribe newly
|
250
|
-
# added methods. Since start_processing is already defined, the
|
251
|
-
# net effect is that start_processing gets called
|
252
|
-
# twice. Therefore, we temporarily switch to protected mode and
|
253
|
-
# change it back later to public.
|
254
|
-
protected
|
255
|
-
def start_processing(event)
|
256
|
-
payload = event.payload
|
257
|
-
params = payload[:params].except(*INTERNAL_PARAMS)
|
258
|
-
format = payload[:format]
|
259
|
-
format = format.to_s.upcase if format.is_a?(Symbol)
|
260
|
-
|
261
|
-
controller = payload[:controller]
|
262
|
-
action = payload[:action]
|
263
|
-
full_name = "#{controller}##{action}"
|
264
|
-
action_name = LogjamAgent.action_name_proc.call(full_name)
|
265
|
-
|
266
|
-
LogjamAgent.request.fields[:action] = action_name
|
267
|
-
|
268
|
-
info "Processing by #{full_name} as #{format}"
|
269
|
-
info " Parameters: #{params.inspect}" unless params.empty?
|
270
|
-
end
|
271
|
-
public :start_processing
|
272
|
-
|
273
|
-
else
|
274
|
-
raise "logjam_agent ActionController monkey patch is not compatible with your Rails version"
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
214
|
+
if defined?(Rails::Railtie)
|
215
|
+
require_relative "rails_support"
|
278
216
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# patch the actioncontroller logsubscriber to set the action on the logjam logger as soon as it starts processing the request
|
2
|
+
require 'action_controller/metal/instrumentation'
|
3
|
+
require 'action_controller/log_subscriber'
|
4
|
+
|
5
|
+
module ActionController #:nodoc:
|
6
|
+
|
7
|
+
class LogSubscriber
|
8
|
+
def start_processing(event)
|
9
|
+
payload = event.payload
|
10
|
+
params = payload[:params].except(*INTERNAL_PARAMS)
|
11
|
+
format = payload[:format]
|
12
|
+
format = format.to_s.upcase if format.is_a?(Symbol)
|
13
|
+
|
14
|
+
controller = payload[:controller]
|
15
|
+
action = payload[:action]
|
16
|
+
full_name = "#{controller}##{action}"
|
17
|
+
action_name = LogjamAgent.action_name_proc.call(full_name)
|
18
|
+
|
19
|
+
LogjamAgent.request.fields[:action] = action_name
|
20
|
+
|
21
|
+
info "Processing by #{full_name} as #{format}"
|
22
|
+
info " Parameters: #{params.inspect}" unless params.empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
begin
|
3
|
+
require 'active_support/parameter_filter'
|
4
|
+
rescue LoadError
|
5
|
+
require_relative '../active_support/parameter_filter'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Extend the Sinatra Request class with some methods to make it look more like an
|
9
|
+
# ActionDispatch request.
|
10
|
+
|
11
|
+
class Sinatra::Request
|
12
|
+
alias_method :method, :request_method
|
13
|
+
def query_parameters; self.GET; end
|
14
|
+
def request_parameters; self.POST; end
|
15
|
+
|
16
|
+
def parameter_filter
|
17
|
+
ActiveSupport::ParameterFilter.new(LogjamAgent.parameter_filters)
|
18
|
+
end
|
19
|
+
|
20
|
+
KV_RE = '[^&;=]+'
|
21
|
+
PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
|
22
|
+
|
23
|
+
def filtered_path
|
24
|
+
return path if query_string.empty?
|
25
|
+
filter = parameter_filter
|
26
|
+
filtered_query_string = query_string.gsub(PAIR_RE) do |_|
|
27
|
+
filter.filter($1 => $2).first.join("=")
|
28
|
+
end
|
29
|
+
"#{path}?#{filtered_query_string}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/logjam_agent/railtie.rb
CHANGED
@@ -80,6 +80,9 @@ module LogjamAgent
|
|
80
80
|
# disable logjam request forwarding by default in test environment
|
81
81
|
LogjamAgent.disable! if Rails.env.test?
|
82
82
|
|
83
|
+
# only sent pings in production like environments
|
84
|
+
LogjamAgent.ensure_ping_at_exit = !%w(test development).include?(Rails.env.to_s)
|
85
|
+
|
83
86
|
# patch controller testing to create a logjam request, because middlewares aren't executed
|
84
87
|
if Rails.env.test?
|
85
88
|
ActiveSupport.on_load(:action_controller) do
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module LogjamAgent
|
2
|
+
class Receiver
|
3
|
+
def initialize
|
4
|
+
@socket = ZMQForwarder.context.socket(ZMQ::ROUTER)
|
5
|
+
@socket.setsockopt(ZMQ::RCVTIMEO, 100)
|
6
|
+
if @socket.bind("inproc://app") < 0
|
7
|
+
raise "ZMQ error on binding: #{ZMQ::Util.error_string}"
|
8
|
+
end
|
9
|
+
at_exit { @socket.close }
|
10
|
+
end
|
11
|
+
|
12
|
+
def receive
|
13
|
+
answer_parts = []
|
14
|
+
if @socket.recv_strings(answer_parts) < 0
|
15
|
+
raise "ZMQ error on receiving: #{ZMQ::Util.error_string}"
|
16
|
+
end
|
17
|
+
answer_parts.shift
|
18
|
+
answer_parts[2] = JSON.parse(answer_parts[2])
|
19
|
+
answer_parts
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'logger'
|
3
|
+
require 'logjam_agent'
|
4
|
+
require 'logjam_agent/middleware'
|
5
|
+
require 'logjam_agent/rack/sinatra_request'
|
6
|
+
require 'logjam_agent/rack/logger'
|
7
|
+
require 'time_bandits'
|
8
|
+
|
9
|
+
module LogjamAgent
|
10
|
+
module Sinatra
|
11
|
+
class Middleware
|
12
|
+
def initialize(app)
|
13
|
+
app_with_logging = LogjamAgent::Rack::Logger.new(app)
|
14
|
+
@app = LogjamAgent::Middleware.new(app_with_logging, :sinatra)
|
15
|
+
end
|
16
|
+
def call(env)
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Helpers
|
22
|
+
def action_name(action_name)
|
23
|
+
LogjamAgent.request.fields[:action] = action_name
|
24
|
+
end
|
25
|
+
|
26
|
+
def logger
|
27
|
+
LogjamAgent.logger
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup_logjam_logger
|
32
|
+
log_path = ENV["APP_LOG_TO_STDOUT"].present? ? STDOUT : "#{settings.root}/log/#{LogjamAgent.environment_name}.log"
|
33
|
+
logger = LogjamAgent::BufferedLogger.new(log_path) rescue LogjamAgent::BufferedLogger.new(STDERR)
|
34
|
+
|
35
|
+
loglevel = settings.respond_to?(:loglevel) ? settings.loglevel : :info
|
36
|
+
logger.level = ::Logger.const_get(loglevel.to_s.upcase)
|
37
|
+
|
38
|
+
LogjamAgent.log_device_log_level = logger.level
|
39
|
+
LogjamAgent.log_device_log_level = ::Logger::ERROR unless %i[test development].include?(settings.environment.to_sym)
|
40
|
+
|
41
|
+
logger.formatter = LogjamAgent::SyslogLikeFormatter.new
|
42
|
+
logger = ActiveSupport::TaggedLogging.new(logger)
|
43
|
+
LogjamAgent.logger = logger
|
44
|
+
ActiveSupport::LogSubscriber.logger = logger
|
45
|
+
|
46
|
+
log_path = ENV["APP_LOG_TO_STDOUT"].present? ? STDOUT : "#{settings.root}/log/logjam_agent_error.log"
|
47
|
+
forwarding_error_logger = ::Logger.new(log_path) rescue ::Logger.new(STDERR)
|
48
|
+
forwarding_error_logger.level = ::Logger::ERROR
|
49
|
+
forwarding_error_logger.formatter = ::Logger::Formatter.new
|
50
|
+
LogjamAgent.forwarding_error_logger = forwarding_error_logger
|
51
|
+
|
52
|
+
truncate_overlong_params = lambda { |key, value|
|
53
|
+
max_size = LogjamAgent.max_logged_size_for(key)
|
54
|
+
if value.is_a?(String) && value.size > max_size
|
55
|
+
value[max_size..-1] = " ... [TRUNCATED]"
|
56
|
+
end
|
57
|
+
}
|
58
|
+
LogjamAgent.parameter_filters << truncate_overlong_params
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.registered(app)
|
62
|
+
app.helpers Helpers
|
63
|
+
LogjamAgent.environment_name = ENV['LOGJAM_ENV'] || app.settings.environment.to_s
|
64
|
+
LogjamAgent.auto_detect_logged_exceptions
|
65
|
+
LogjamAgent.disable! if app.settings.environment.to_sym == :test
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# For classic apps.
|
71
|
+
Sinatra.register LogjamAgent::Sinatra
|
72
|
+
|
73
|
+
# We already supply a logger.
|
74
|
+
Sinatra::Base.class_eval do
|
75
|
+
class << self
|
76
|
+
def setup_logging(builder); end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Patch Sinatra's render logic to compute corrected view times.
|
81
|
+
module LogjamAgent
|
82
|
+
module ComputeRenderTimes
|
83
|
+
def render(engine, data, options = {}, locals = {}, &block)
|
84
|
+
consumed_before_rendering = TimeBandits.consumed
|
85
|
+
result = exception = nil
|
86
|
+
duration = Benchmark.ms do
|
87
|
+
begin
|
88
|
+
result = super
|
89
|
+
rescue => exception
|
90
|
+
end
|
91
|
+
end
|
92
|
+
consumed_during_rendering = TimeBandits.consumed - consumed_before_rendering
|
93
|
+
duration -= consumed_during_rendering
|
94
|
+
raise exception if exception
|
95
|
+
result
|
96
|
+
ensure
|
97
|
+
Thread.current.thread_variable_set(
|
98
|
+
:time_bandits_completed_info,
|
99
|
+
[ duration, ["Views: %.3fms" % duration.to_f], duration, "" ]
|
100
|
+
)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
Sinatra::Base.prepend LogjamAgent::ComputeRenderTimes
|
106
|
+
|
107
|
+
# Define exception, but don't do anything about it. Sneaky!
|
108
|
+
module ActionDispatch
|
109
|
+
module RemoteIp
|
110
|
+
class IpSpoofAttackError < StandardError; end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Add GC time bandit
|
115
|
+
TimeBandits.reset
|
116
|
+
TimeBandits.add TimeBandits::TimeConsumers::GarbageCollection.instance if GC.respond_to? :enable_stats
|
@@ -41,7 +41,7 @@ module LogjamAgent
|
|
41
41
|
"#{format_severity(severity)} #{format_time(timestamp)}#{render_attributes}#{format_host_info(progname)}: #{format_message(msg)}#{@newline}"
|
42
42
|
end
|
43
43
|
|
44
|
-
if !defined?(Rails) || Rails.env.development?
|
44
|
+
if !defined?(Rails::Railtie) || Rails.env.development?
|
45
45
|
def format_host_info(progname); ""; end
|
46
46
|
else
|
47
47
|
def format_host_info(progname)
|
data/lib/logjam_agent/util.rb
CHANGED
@@ -62,7 +62,12 @@ module LogjamAgent
|
|
62
62
|
protocol, host, port = %r{\A(?:([^:]+)://)?([^:]+)(?::(\d+))?\z}.match(spec).captures
|
63
63
|
protocol ||= "tcp"
|
64
64
|
port ||= default_port
|
65
|
-
|
65
|
+
if protocol == "inproc"
|
66
|
+
# should only be used for integration tests
|
67
|
+
"#{protocol}://#{host}"
|
68
|
+
else
|
69
|
+
"#{protocol}://#{host}:#{port}"
|
70
|
+
end
|
66
71
|
end
|
67
72
|
end
|
68
73
|
end
|
data/lib/logjam_agent/version.rb
CHANGED
@@ -53,7 +53,12 @@ module LogjamAgent
|
|
53
53
|
def socket
|
54
54
|
return @socket if @socket
|
55
55
|
@socket = self.class.context.socket(ZMQ::DEALER)
|
56
|
-
|
56
|
+
raise "ZMQ error on socket creation: #{ZMQ::Util.error_string}" if @socket.nil?
|
57
|
+
if LogjamAgent.ensure_ping_at_exit
|
58
|
+
ensure_ping_at_exit
|
59
|
+
else
|
60
|
+
at_exit { reset }
|
61
|
+
end
|
57
62
|
@socket.setsockopt(ZMQ::LINGER, @config[:linger])
|
58
63
|
@socket.setsockopt(ZMQ::SNDHWM, @config[:snd_hwm])
|
59
64
|
@socket.setsockopt(ZMQ::RCVHWM, @config[:rcv_hwm])
|
@@ -98,8 +103,9 @@ module LogjamAgent
|
|
98
103
|
info = pack_info(@sequence = next_fixnum(@sequence))
|
99
104
|
parts = [app_env, key, data, info]
|
100
105
|
if socket.send_strings(parts, ZMQ::DONTWAIT) < 0
|
106
|
+
error = ZMQ::Util.error_string
|
101
107
|
reset if connection_specs.size > 1
|
102
|
-
raise "ZMQ error on publishing: #{
|
108
|
+
raise "ZMQ error on publishing: #{error}"
|
103
109
|
end
|
104
110
|
end
|
105
111
|
|
data/test/sinatra_app.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'logjam_agent/sinatra'
|
4
|
+
|
5
|
+
class SinatraTestApp < Sinatra::Base
|
6
|
+
register LogjamAgent::Sinatra
|
7
|
+
|
8
|
+
use LogjamAgent::Sinatra::Middleware
|
9
|
+
|
10
|
+
configure do
|
11
|
+
set :root, File.expand_path('../..', __FILE__)
|
12
|
+
set :environment, :test
|
13
|
+
set :loglevel, :debug
|
14
|
+
setup_logjam_logger
|
15
|
+
|
16
|
+
LogjamAgent.application_name = "myapp"
|
17
|
+
LogjamAgent.add_forwarder(:zmq, :host => "inproc://app")
|
18
|
+
LogjamAgent.parameter_filters << :password
|
19
|
+
LogjamAgent.ensure_ping_at_exit = false
|
20
|
+
end
|
21
|
+
|
22
|
+
before '/index' do
|
23
|
+
action_name "Simple#index"
|
24
|
+
end
|
25
|
+
|
26
|
+
get '/index' do
|
27
|
+
logger.info 'Hello World!'
|
28
|
+
'Hello World!'
|
29
|
+
end
|
30
|
+
|
31
|
+
run! if __FILE__ == $0
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'logjam_agent/sinatra'
|
4
|
+
|
5
|
+
use LogjamAgent::Sinatra::Middleware
|
6
|
+
|
7
|
+
configure do
|
8
|
+
set :root, File.expand_path('../..', __FILE__)
|
9
|
+
set :environment, :test
|
10
|
+
set :loglevel, :debug
|
11
|
+
setup_logjam_logger
|
12
|
+
|
13
|
+
LogjamAgent.application_name = "myapp"
|
14
|
+
LogjamAgent.add_forwarder(
|
15
|
+
:zmq,
|
16
|
+
:host => "localhost",
|
17
|
+
:port => 9604,
|
18
|
+
:linger => 10,
|
19
|
+
:snd_hwm => 10,
|
20
|
+
:rcv_hwm => 10,
|
21
|
+
:rcv_timeo => 10,
|
22
|
+
:snd_timeo => 10
|
23
|
+
)
|
24
|
+
LogjamAgent.parameter_filters << :password
|
25
|
+
end
|
26
|
+
|
27
|
+
get '/index' do
|
28
|
+
action_name "Simple#index"
|
29
|
+
logger.info 'Hello World!'
|
30
|
+
'Hello World!'
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative "test_helper.rb"
|
2
|
+
require_relative "sinatra_classic_app"
|
3
|
+
require "rack/test"
|
4
|
+
|
5
|
+
module LogjamAgent
|
6
|
+
class SinatraClassicTest < MiniTest::Test
|
7
|
+
|
8
|
+
include ::Rack::Test::Methods
|
9
|
+
|
10
|
+
def app
|
11
|
+
::Sinatra::Application
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_root
|
15
|
+
get '/index?mumu=1&password=5'
|
16
|
+
assert_equal 'Hello World!', last_response.body
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative "test_helper.rb"
|
2
|
+
require_relative "sinatra_app"
|
3
|
+
require "rack/test"
|
4
|
+
|
5
|
+
module LogjamAgent
|
6
|
+
class SinatraTest < MiniTest::Test
|
7
|
+
def setup
|
8
|
+
@@receiver ||= LogjamAgent::Receiver.new
|
9
|
+
LogjamAgent.enable!
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
LogjamAgent.disable!
|
14
|
+
end
|
15
|
+
|
16
|
+
def logjam_message
|
17
|
+
@@receiver.receive
|
18
|
+
end
|
19
|
+
|
20
|
+
include ::Rack::Test::Methods
|
21
|
+
|
22
|
+
def app
|
23
|
+
SinatraTestApp
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_root
|
27
|
+
get '/index?mumu=1&password=5'
|
28
|
+
assert_equal 'Hello World!', last_response.body
|
29
|
+
assert_equal 200, last_response.status
|
30
|
+
|
31
|
+
stream, topic, payload = logjam_message
|
32
|
+
assert_equal "myapp-test", stream
|
33
|
+
assert_equal "logs.myapp.test", topic
|
34
|
+
assert_equal 200, payload["code"]
|
35
|
+
assert_equal "Simple#index", payload["action"]
|
36
|
+
assert_kind_of Float, payload["total_time"]
|
37
|
+
assert_kind_of String, payload["started_at"]
|
38
|
+
assert_kind_of Integer, payload["started_ms"]
|
39
|
+
assert_kind_of String, payload["ip"]
|
40
|
+
# assert_kind_of Float, payload["view_time"]
|
41
|
+
lines = payload["lines"]
|
42
|
+
assert_match(/Started GET.*password=\[FILTERED\]/, lines[0][2])
|
43
|
+
assert_match(/Hello World/, lines[1][2])
|
44
|
+
assert_match(/Completed 200 OK/, lines[2][2])
|
45
|
+
assert_nil(lines[3])
|
46
|
+
request_info = payload["request_info"]
|
47
|
+
method, url, query_parameters = request_info.values_at(*%w(method url query_parameters))
|
48
|
+
assert_equal method, "GET"
|
49
|
+
assert_equal url, "/index?mumu=1&password=[FILTERED]"
|
50
|
+
assert_equal(query_parameters, { "mumu" => "1", "password" => "[FILTERED]" })
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -8,4 +8,9 @@ class MiniTest::Test
|
|
8
8
|
extend ActiveSupport::Testing::Declarative
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
12
|
+
require "logjam_agent"
|
13
|
+
require "logjam_agent/receiver"
|
14
|
+
|
15
|
+
# for Sinatra
|
16
|
+
ENV['RACK_ENV'] = "test"
|
data/test/util_test.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logjam_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.31.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Kaes
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -122,6 +122,48 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sinatra
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rack-test
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: appraisal
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
125
167
|
- !ruby/object:Gem::Dependency
|
126
168
|
name: activesupport
|
127
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,14 +184,14 @@ dependencies:
|
|
142
184
|
requirements:
|
143
185
|
- - ">="
|
144
186
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
187
|
+
version: 0.12.2
|
146
188
|
type: :runtime
|
147
189
|
prerelease: false
|
148
190
|
version_requirements: !ruby/object:Gem::Requirement
|
149
191
|
requirements:
|
150
192
|
- - ">="
|
151
193
|
- !ruby/object:Gem::Version
|
152
|
-
version: 0.
|
194
|
+
version: 0.12.2
|
153
195
|
- !ruby/object:Gem::Dependency
|
154
196
|
name: ffi-rzmq-core
|
155
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,32 +227,39 @@ executables: []
|
|
185
227
|
extensions: []
|
186
228
|
extra_rdoc_files: []
|
187
229
|
files:
|
188
|
-
- ".gitignore"
|
189
|
-
- Gemfile
|
190
230
|
- README.md
|
191
231
|
- Rakefile
|
192
232
|
- lib/logjam_agent.rb
|
193
233
|
- lib/logjam_agent/actionpack/lib/action_dispatch/middleware/remote_ip.rb
|
234
|
+
- lib/logjam_agent/active_support/core_ext/array/extract.rb
|
235
|
+
- lib/logjam_agent/active_support/parameter_filter.rb
|
194
236
|
- lib/logjam_agent/buffered_logger.rb
|
195
237
|
- lib/logjam_agent/forwarders.rb
|
196
238
|
- lib/logjam_agent/middleware.rb
|
197
239
|
- lib/logjam_agent/rack/logger.rb
|
240
|
+
- lib/logjam_agent/rack/rails_support.rb
|
241
|
+
- lib/logjam_agent/rack/sinatra_request.rb
|
198
242
|
- lib/logjam_agent/railtie.rb
|
243
|
+
- lib/logjam_agent/receiver.rb
|
199
244
|
- lib/logjam_agent/request.rb
|
245
|
+
- lib/logjam_agent/sinatra.rb
|
200
246
|
- lib/logjam_agent/syslog_like_formatter.rb
|
201
247
|
- lib/logjam_agent/util.rb
|
202
248
|
- lib/logjam_agent/version.rb
|
203
249
|
- lib/logjam_agent/zmq_forwarder.rb
|
204
|
-
- logjam_agent.gemspec
|
205
|
-
- script/console
|
206
250
|
- test/request_test.rb
|
251
|
+
- test/sinatra_app.rb
|
252
|
+
- test/sinatra_classic_app.rb
|
253
|
+
- test/sinatra_classic_test.rb
|
254
|
+
- test/sinatra_test.rb
|
207
255
|
- test/test_helper.rb
|
208
256
|
- test/util_test.rb
|
209
257
|
- test/zmq_forwarder_test.rb
|
210
|
-
homepage:
|
211
|
-
licenses:
|
258
|
+
homepage: https://github.com/skaes/logjam_agent
|
259
|
+
licenses:
|
260
|
+
- MIT
|
212
261
|
metadata: {}
|
213
|
-
post_install_message:
|
262
|
+
post_install_message:
|
214
263
|
rdoc_options: []
|
215
264
|
require_paths:
|
216
265
|
- lib
|
@@ -225,12 +274,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
225
274
|
- !ruby/object:Gem::Version
|
226
275
|
version: '0'
|
227
276
|
requirements: []
|
228
|
-
rubygems_version: 3.
|
229
|
-
signing_key:
|
277
|
+
rubygems_version: 3.1.2
|
278
|
+
signing_key:
|
230
279
|
specification_version: 4
|
231
280
|
summary: Logjam client library to be used with logjam
|
232
281
|
test_files:
|
282
|
+
- test/sinatra_app.rb
|
283
|
+
- test/sinatra_classic_test.rb
|
284
|
+
- test/sinatra_classic_app.rb
|
233
285
|
- test/request_test.rb
|
234
|
-
- test/test_helper.rb
|
235
|
-
- test/util_test.rb
|
236
286
|
- test/zmq_forwarder_test.rb
|
287
|
+
- test/util_test.rb
|
288
|
+
- test/test_helper.rb
|
289
|
+
- test/sinatra_test.rb
|
data/Gemfile
DELETED
data/logjam_agent.gemspec
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "logjam_agent/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "logjam_agent"
|
7
|
-
s.version = LogjamAgent::VERSION
|
8
|
-
s.authors = ["Stefan Kaes"]
|
9
|
-
s.email = ["stefan.kaes@xing.com"]
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = %q{Logjam client library to be used with logjam}
|
12
|
-
s.description = %q{Logjam logger and request information forwarding}
|
13
|
-
|
14
|
-
s.files = `git ls-files`.split("\n")
|
15
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
-
s.require_paths = ["lib"]
|
18
|
-
|
19
|
-
s.add_development_dependency "rake"
|
20
|
-
s.add_development_dependency "i18n"
|
21
|
-
s.add_development_dependency "snappy"
|
22
|
-
s.add_development_dependency "lz4-ruby"
|
23
|
-
s.add_development_dependency "oj"
|
24
|
-
s.add_development_dependency "byebug"
|
25
|
-
s.add_development_dependency "minitest"
|
26
|
-
s.add_development_dependency "mocha"
|
27
|
-
|
28
|
-
s.add_runtime_dependency "activesupport"
|
29
|
-
s.add_runtime_dependency "time_bandits", [">= 0.6.0"]
|
30
|
-
s.add_runtime_dependency "ffi-rzmq-core", [">= 1.0.5"]
|
31
|
-
s.add_runtime_dependency "ffi-rzmq", [">= 2.0.4"]
|
32
|
-
end
|
data/script/console
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'optparse'
|
3
|
-
|
4
|
-
options = { }
|
5
|
-
OptionParser.new do |opt|
|
6
|
-
opt.banner = "Usage: console [options]"
|
7
|
-
opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
|
8
|
-
opt.parse!(ARGV)
|
9
|
-
end
|
10
|
-
|
11
|
-
lib_dir = File.expand_path("../../lib/", __FILE__)
|
12
|
-
libs = " -r irb/completion"
|
13
|
-
libs << " -I #{lib_dir}"
|
14
|
-
libs << " -r #{lib_dir}/logjam_agent.rb"
|
15
|
-
|
16
|
-
if options[:debugger]
|
17
|
-
begin
|
18
|
-
require 'byebug'
|
19
|
-
libs << " -r byebug"
|
20
|
-
puts "=> Debugger enabled"
|
21
|
-
rescue Exception
|
22
|
-
puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
|
23
|
-
exit
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
28
|
-
exec "#{irb} #{libs} --simple-prompt"
|