logster 1.2.11 → 1.3.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -17
  3. data/.travis.yml +15 -16
  4. data/CHANGELOG.md +130 -130
  5. data/Gemfile +4 -4
  6. data/Guardfile +8 -8
  7. data/LICENSE.txt +22 -22
  8. data/README.md +99 -96
  9. data/Rakefile +24 -23
  10. data/assets/fonts/FontAwesome.otf +0 -0
  11. data/assets/fonts/fontawesome-webfont.eot +0 -0
  12. data/assets/fonts/fontawesome-webfont.svg +639 -639
  13. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  14. data/assets/fonts/fontawesome-webfont.woff +0 -0
  15. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  16. data/assets/images/Icon-144_rounded.png +0 -0
  17. data/assets/images/Icon-144_square.png +0 -0
  18. data/assets/images/icon_144x144.png +0 -0
  19. data/assets/images/icon_64x64.png +0 -0
  20. data/assets/javascript/client-app.js +81 -0
  21. data/assets/javascript/vendor.js +5302 -0
  22. data/assets/stylesheets/client-app.css +1 -0
  23. data/assets/stylesheets/vendor.css +4 -0
  24. data/build_client_app.sh +12 -0
  25. data/client-app/.editorconfig +20 -0
  26. data/client-app/.ember-cli +9 -0
  27. data/client-app/.eslintignore +19 -0
  28. data/client-app/.eslintrc.js +46 -0
  29. data/client-app/.gitignore +23 -0
  30. data/client-app/.travis.yml +27 -0
  31. data/client-app/.watchmanconfig +3 -0
  32. data/client-app/README.md +57 -0
  33. data/client-app/app/app.js +14 -0
  34. data/client-app/app/components/message-info.js +18 -0
  35. data/client-app/app/components/message-row.js +45 -0
  36. data/client-app/app/components/panel-resizer.js +75 -0
  37. data/client-app/app/components/tab-contents.js +27 -0
  38. data/client-app/app/components/tab-link.js +5 -0
  39. data/client-app/app/components/tabbed-section.js +32 -0
  40. data/client-app/app/components/time-formatter.js +25 -0
  41. data/client-app/app/components/update-time.js +21 -0
  42. data/client-app/app/controllers/index.js +83 -0
  43. data/client-app/app/controllers/show.js +13 -0
  44. data/client-app/app/index.html +29 -0
  45. data/client-app/app/initializers/app-init.js +55 -0
  46. data/client-app/app/lib/preload.js +14 -0
  47. data/client-app/app/lib/utilities.js +140 -0
  48. data/client-app/app/models/message-collection.js +158 -0
  49. data/client-app/app/models/message.js +99 -0
  50. data/client-app/app/resolver.js +3 -0
  51. data/client-app/app/router.js +14 -0
  52. data/client-app/app/routes/index.js +53 -0
  53. data/client-app/app/routes/show.js +14 -0
  54. data/{assets/stylesheets → client-app/app/styles}/app.css +387 -390
  55. data/{assets/javascript → client-app/app}/templates/application.hbs +2 -2
  56. data/client-app/app/templates/components/message-info.hbs +44 -0
  57. data/{assets/javascript → client-app/app/templates}/components/message-row.hbs +17 -17
  58. data/client-app/app/templates/components/tabbed-section.hbs +10 -0
  59. data/client-app/app/templates/components/time-formatter.hbs +1 -0
  60. data/{assets/javascript → client-app/app}/templates/index.hbs +57 -57
  61. data/{assets/javascript → client-app/app}/templates/show.hbs +4 -4
  62. data/client-app/config/environment.js +51 -0
  63. data/client-app/config/optional-features.json +3 -0
  64. data/client-app/config/targets.js +18 -0
  65. data/client-app/ember-cli-build.js +29 -0
  66. data/client-app/package-lock.json +11365 -0
  67. data/client-app/package.json +56 -0
  68. data/client-app/testem.js +25 -0
  69. data/client-app/tests/index.html +34 -0
  70. data/client-app/tests/integration/components/message-info-test.js +26 -0
  71. data/client-app/tests/integration/components/message-row-test.js +26 -0
  72. data/client-app/tests/integration/components/panel-resizer-test.js +26 -0
  73. data/client-app/tests/integration/components/tab-contents-test.js +26 -0
  74. data/client-app/tests/integration/components/tab-link-test.js +26 -0
  75. data/client-app/tests/integration/components/tabbed-section-test.js +26 -0
  76. data/client-app/tests/integration/components/time-formatter-test.js +26 -0
  77. data/client-app/tests/integration/components/update-time-test.js +26 -0
  78. data/client-app/tests/test-helper.js +8 -0
  79. data/client-app/tests/unit/controllers/index-test.js +12 -0
  80. data/client-app/tests/unit/controllers/show-test.js +12 -0
  81. data/client-app/tests/unit/initializers/app-init-test.js +31 -0
  82. data/client-app/tests/unit/routes/index-test.js +11 -0
  83. data/client-app/tests/unit/routes/show-test.js +11 -0
  84. data/lib/examples/sidekiq_logster_reporter.rb +21 -21
  85. data/lib/logster.rb +54 -54
  86. data/lib/logster/base_store.rb +130 -130
  87. data/lib/logster/configuration.rb +25 -25
  88. data/lib/logster/ignore_pattern.rb +65 -65
  89. data/lib/logster/logger.rb +102 -101
  90. data/lib/logster/message.rb +227 -226
  91. data/lib/logster/middleware/debug_exceptions.rb +26 -26
  92. data/lib/logster/middleware/reporter.rb +56 -54
  93. data/lib/logster/middleware/viewer.rb +220 -251
  94. data/lib/logster/rails/railtie.rb +58 -58
  95. data/lib/logster/redis_store.rb +481 -477
  96. data/lib/logster/version.rb +3 -3
  97. data/lib/logster/web.rb +14 -14
  98. data/logster.gemspec +34 -33
  99. data/test/examples/test_sidekiq_reporter_example.rb +46 -46
  100. data/test/fake_data/Gemfile +4 -4
  101. data/test/fake_data/generate.rb +10 -10
  102. data/test/logster/middleware/test_reporter.rb +21 -21
  103. data/test/logster/middleware/test_viewer.rb +96 -70
  104. data/test/logster/test_base_store.rb +147 -147
  105. data/test/logster/test_ignore_pattern.rb +41 -41
  106. data/test/logster/test_logger.rb +74 -74
  107. data/test/logster/test_message.rb +34 -34
  108. data/test/logster/test_redis_rate_limiter.rb +230 -230
  109. data/test/logster/test_redis_store.rb +427 -414
  110. data/test/test_helper.rb +38 -37
  111. data/vendor/assets/javascripts/logster.js.erb +39 -39
  112. metadata +83 -24
  113. data/assets/javascript/app.js +0 -817
  114. data/assets/javascript/components/message-info.hbs +0 -47
  115. data/assets/javascript/components/panel-resizer.hbs +0 -0
  116. data/assets/javascript/components/tab-contents.hbs +0 -1
  117. data/assets/javascript/components/tab-link.hbs +0 -1
  118. data/assets/javascript/components/tabbed-section.hbs +0 -6
  119. data/assets/javascript/external/ember-template-compiler.js +0 -22346
  120. data/assets/javascript/external/ember.js +0 -58500
  121. data/assets/javascript/external/ember.min.js +0 -17
  122. data/assets/javascript/external/jquery.min.js +0 -5
  123. data/assets/javascript/external/lodash.min.js +0 -87
  124. data/assets/javascript/external/moment.min.js +0 -6
  125. data/assets/stylesheets/font-awesome.min.css +0 -4
  126. data/bower.json +0 -25
@@ -1,101 +1,102 @@
1
- require 'logger'
2
-
3
- module Logster
4
- class Logger < ::Logger
5
- LOGSTER_ENV = "logster_env".freeze
6
-
7
- attr_accessor :store, :skip_store
8
- attr_reader :chained
9
-
10
- def initialize(store)
11
- super(nil)
12
- @store = store
13
- @override_levels = nil
14
- end
15
-
16
- def override_level=(val)
17
- tid = Thread.current.object_id
18
-
19
- ol = @override_levels
20
- if val.nil? && ol && ol.key?(tid)
21
- ol.delete(tid)
22
- @override_levels = nil if ol.length == 0
23
- elsif val
24
- (@override_levels ||= {})[tid] = val
25
- end
26
- end
27
-
28
- def chain(logger)
29
- @chained ||= []
30
- @chained << logger
31
- end
32
-
33
- def add_to_chained(logger, severity, message, progname, opts=nil, &block)
34
- if logger.respond_to? :skip_store
35
- old = logger.skip_store
36
- logger.skip_store = @skip_store
37
- end
38
-
39
- if logger.is_a?(self.class)
40
- logger.add(severity, message, progname, opts, &block)
41
- else
42
- logger.add(severity, message, progname, &block)
43
- end
44
- ensure
45
- if logger.respond_to? :skip_store
46
- logger.skip_store = old
47
- end
48
- end
49
-
50
- def add(*args, &block)
51
- add_with_opts(*args,&block)
52
- end
53
-
54
- def level
55
- ol = @override_levels
56
- (ol && ol[Thread.current.object_id]) || @level
57
- end
58
-
59
- def add_with_opts(severity, message, progname, opts=nil, &block)
60
- if severity < level
61
- return true
62
- end
63
-
64
- if @chained
65
- i = 0
66
- # micro optimise for logging
67
- while i < @chained.length
68
- # TODO double yielding blocks
69
- begin
70
- add_to_chained(@chained[i], severity, message, progname, opts, &block)
71
- rescue => e
72
- # don't blow up if STDERR is somehow closed
73
- STDERR.puts "Failed to report message to chained logger #{e}" rescue nil
74
- end
75
- i += 1
76
- end
77
- end
78
-
79
- progname ||= @progname
80
- if message.nil?
81
- if block_given?
82
- message = yield
83
- else
84
- message = progname
85
- progname = @progname
86
- end
87
- end
88
-
89
- return if @skip_store
90
-
91
- opts ||= {}
92
- opts[:env] ||= Thread.current[LOGSTER_ENV]
93
-
94
- @store.report(severity, progname, message, opts)
95
-
96
- rescue => e
97
- # don't blow up if STDERR is somehow closed
98
- STDERR.puts "Failed to report error: #{e} #{severity} #{message} #{progname}" rescue nil
99
- end
100
- end
101
- end
1
+ require 'logger'
2
+
3
+ module Logster
4
+ class Logger < ::Logger
5
+ LOGSTER_ENV = "logster_env".freeze
6
+
7
+ attr_accessor :store, :skip_store
8
+ attr_reader :chained
9
+
10
+ def initialize(store)
11
+ super(nil)
12
+ @store = store
13
+ @override_levels = nil
14
+ @chained = []
15
+ @skip_store = false
16
+ end
17
+
18
+ def override_level=(val)
19
+ tid = Thread.current.object_id
20
+
21
+ ol = @override_levels
22
+ if val.nil? && ol && ol.key?(tid)
23
+ ol.delete(tid)
24
+ @override_levels = nil if ol.length == 0
25
+ elsif val
26
+ (@override_levels ||= {})[tid] = val
27
+ end
28
+ end
29
+
30
+ def chain(logger)
31
+ @chained << logger
32
+ end
33
+
34
+ def add_to_chained(logger, severity, message, progname, opts=nil, &block)
35
+ if logger.respond_to? :skip_store
36
+ old = logger.skip_store
37
+ logger.skip_store = @skip_store
38
+ end
39
+
40
+ if logger.is_a?(self.class)
41
+ logger.add(severity, message, progname, opts, &block)
42
+ else
43
+ logger.add(severity, message, progname, &block)
44
+ end
45
+ ensure
46
+ if logger.respond_to? :skip_store
47
+ logger.skip_store = old
48
+ end
49
+ end
50
+
51
+ def add(*args, &block)
52
+ add_with_opts(*args,&block)
53
+ end
54
+
55
+ def level
56
+ ol = @override_levels
57
+ (ol && ol[Thread.current.object_id]) || @level
58
+ end
59
+
60
+ def add_with_opts(severity, message, progname, opts=nil, &block)
61
+ if severity < level
62
+ return true
63
+ end
64
+
65
+ if @chained
66
+ i = 0
67
+ # micro optimise for logging
68
+ while i < @chained.length
69
+ # TODO double yielding blocks
70
+ begin
71
+ add_to_chained(@chained[i], severity, message, progname, opts, &block)
72
+ rescue => e
73
+ # don't blow up if STDERR is somehow closed
74
+ STDERR.puts "Failed to report message to chained logger #{e}" rescue nil
75
+ end
76
+ i += 1
77
+ end
78
+ end
79
+
80
+ progname ||= @progname
81
+ if message.nil?
82
+ if block_given?
83
+ message = yield
84
+ else
85
+ message = progname
86
+ progname = @progname
87
+ end
88
+ end
89
+
90
+ return if @skip_store
91
+
92
+ opts ||= {}
93
+ opts[:env] ||= Thread.current[LOGSTER_ENV]
94
+
95
+ @store.report(severity, progname, message, opts)
96
+
97
+ rescue => e
98
+ # don't blow up if STDERR is somehow closed
99
+ STDERR.puts "Failed to report error: #{e} #{severity} #{message} #{progname}" rescue nil
100
+ end
101
+ end
102
+ end
@@ -1,226 +1,227 @@
1
- require 'digest/sha1'
2
- require 'securerandom'
3
-
4
- module Logster
5
-
6
- MAX_GROUPING_LENGTH = 50
7
-
8
- class Message
9
- LOGSTER_ENV = "_logster_env".freeze
10
- ALLOWED_ENV = %w{
11
- HTTP_HOST
12
- REQUEST_URI
13
- REQUEST_METHOD
14
- HTTP_USER_AGENT
15
- HTTP_ACCEPT
16
- HTTP_REFERER
17
- HTTP_X_FORWARDED_FOR
18
- HTTP_X_REAL_IP
19
- hostname
20
- process_id
21
- application_version
22
- }
23
-
24
- attr_accessor :timestamp, :severity, :progname, :message, :key, :backtrace, :count, :env, :protected, :first_timestamp
25
-
26
- def initialize(severity, progname, message, timestamp = nil, key = nil)
27
- @timestamp = timestamp || get_timestamp
28
- @severity = severity
29
- @progname = progname
30
- @message = message
31
- @key = key || SecureRandom.hex
32
- @backtrace = nil
33
- @count = 1
34
- @protected = false
35
- end
36
-
37
- def to_h
38
- h = {
39
- message: @message,
40
- progname: @progname,
41
- severity: @severity,
42
- timestamp: @timestamp,
43
- key: @key,
44
- backtrace: @backtrace,
45
- count: @count,
46
- env: @env,
47
- protected: @protected
48
- }
49
-
50
- if @first_timestamp
51
- h[:first_timestamp] = @first_timestamp
52
- end
53
-
54
- h
55
- end
56
-
57
- def to_json(opts = nil)
58
- JSON.fast_generate(to_h, opts)
59
- end
60
-
61
- def self.from_json(json)
62
- parsed = ::JSON.parse(json)
63
- msg = new( parsed["severity"],
64
- parsed["progname"],
65
- parsed["message"],
66
- parsed["timestamp"],
67
- parsed["key"] )
68
- msg.backtrace = parsed["backtrace"]
69
- msg.env = parsed["env"]
70
- msg.count = parsed["count"]
71
- msg.protected = parsed["protected"]
72
- msg.first_timestamp = parsed["first_timestamp"]
73
- msg
74
- end
75
-
76
- def self.hostname
77
- @hostname ||= `hostname`.strip! rescue "<unknown>"
78
- end
79
-
80
- def populate_from_env(env)
81
- env ||= {}
82
- @env = Message.populate_from_env(self.class.default_env.merge env)
83
- end
84
-
85
- def self.default_env
86
- env = {
87
- "hostname" => hostname,
88
- "process_id" => Process.pid
89
- }
90
- env["application_version"] = Logster.config.application_version if Logster.config.application_version
91
- env
92
- end
93
-
94
- # in its own method so it can be overridden
95
- def grouping_hash
96
- return { message: self.message, severity: self.severity, backtrace: self.backtrace }
97
- end
98
-
99
- # todo - memoize?
100
- def grouping_key
101
- Digest::SHA1.hexdigest JSON.fast_generate grouping_hash
102
- end
103
-
104
- # todo - memoize?
105
- def solved_keys
106
- if (versions=env["application_version"]) &&
107
- (backtrace && backtrace.length > 0)
108
- versions = [versions] if String === versions
109
-
110
- versions.map do |version|
111
- Digest::SHA1.hexdigest "#{version} #{backtrace}"
112
- end
113
- end
114
- end
115
-
116
- def is_similar?(other)
117
- self.grouping_key == other.grouping_key
118
- end
119
-
120
- def merge_similar_message(other)
121
- self.first_timestamp ||= self.timestamp
122
- self.timestamp = [self.timestamp,other.timestamp].max
123
- other_env = JSON.load JSON.fast_generate other.env
124
- other_env.keys.each do |env_key|
125
- self.env[env_key] = Message.env_merge_helper(self.env[env_key], other_env[env_key])
126
- end
127
- end
128
-
129
- def self.populate_from_env(env)
130
- env[LOGSTER_ENV] ||= begin
131
- unless env.include? "rack.input"
132
- # Not a web request
133
- return env
134
- end
135
- scrubbed = default_env
136
- request = Rack::Request.new(env)
137
- params = {}
138
- request.params.each do |k,v|
139
- if k.include? "password"
140
- params[k] = "[redacted]"
141
- elsif Array === v
142
- params[k] = v[0..20]
143
- else
144
- params[k] = v && v[0..100]
145
- end
146
- end
147
- scrubbed["params"] = params if params.length > 0
148
- ALLOWED_ENV.map{ |k|
149
- scrubbed[k] = env[k] if env[k]
150
- }
151
- scrubbed
152
- end
153
- end
154
-
155
- def <=>(other)
156
- time = self.timestamp <=> other.timestamp
157
- return time if time && time != 0
158
-
159
- self.key <=> other.key
160
- end
161
-
162
- def =~(pattern)
163
- case pattern
164
- when Hash
165
- IgnorePattern.new(nil, pattern).matches? self
166
- when String
167
- IgnorePattern.new(pattern, nil).matches? self
168
- when Regexp
169
- IgnorePattern.new(pattern, nil).matches? self
170
- when IgnorePattern
171
- pattern.matches? self
172
- else
173
- nil
174
- end
175
- end
176
-
177
- protected
178
-
179
- def get_timestamp
180
- (Time.new.to_f * 1000).to_i
181
- end
182
-
183
- private
184
-
185
- def self.env_merge_helper(self_value, other_value)
186
- other_value = other_value.to_s if Symbol === other_value
187
-
188
- if (Hash === self_value || self_value.nil?) && (Hash === other_value || other_value.nil?) && (!self_value.nil? || !other_value.nil?)
189
- # one or both is a hash but not neither -> recurse on the keys
190
- self_value = {} unless self_value
191
- other_value = {} unless other_value
192
- shared_keys = self_value.keys | (other_value.keys rescue [])
193
- shared_keys.each do |key|
194
- self_value[key] = env_merge_helper(self_value[key], other_value[key])
195
- end
196
- self_value
197
- elsif self_value.is_a?(Array) && !other_value.is_a?(Array)
198
- # Already have grouped data, so append to array (it's actually a set)
199
- self_value << other_value unless self_value.include?(other_value) || self_value.length >= Logster::MAX_GROUPING_LENGTH
200
- self_value
201
- elsif !self_value.is_a?(Array)
202
- if self_value == other_value
203
- self_value
204
- else
205
- [self_value, other_value]
206
- end
207
- else
208
- # They're both arrays.
209
- # Three cases:
210
- # self = [1,2,3] and other = [1,2,4] -> make into array of array
211
- # self = [] and other = [1,2,4] -> make into array of array
212
- # self = [[1,2,3], [1,2,5]] and other = [1,2,4] -> append to array
213
- if self_value.length > 0 && self_value[0].is_a?(Array)
214
- self_value << other_value unless self_value.include?(other_value) || self_value.length >= Logster::MAX_GROUPING_LENGTH
215
- self_value
216
- else
217
- if self_value == other_value
218
- self_value
219
- else
220
- [self_value, other_value]
221
- end
222
- end
223
- end
224
- end
225
- end
226
- end
1
+ require 'digest/sha1'
2
+ require 'securerandom'
3
+
4
+ module Logster
5
+
6
+ MAX_GROUPING_LENGTH = 50
7
+
8
+ class Message
9
+ LOGSTER_ENV = "_logster_env".freeze
10
+ ALLOWED_ENV = %w{
11
+ HTTP_HOST
12
+ REQUEST_URI
13
+ REQUEST_METHOD
14
+ HTTP_USER_AGENT
15
+ HTTP_ACCEPT
16
+ HTTP_REFERER
17
+ HTTP_X_FORWARDED_FOR
18
+ HTTP_X_REAL_IP
19
+ hostname
20
+ process_id
21
+ application_version
22
+ }
23
+
24
+ attr_accessor :timestamp, :severity, :progname, :message, :key, :backtrace, :count, :env, :protected, :first_timestamp
25
+
26
+ def initialize(severity, progname, message, timestamp = nil, key = nil)
27
+ @timestamp = timestamp || get_timestamp
28
+ @severity = severity
29
+ @progname = progname
30
+ @message = message
31
+ @key = key || SecureRandom.hex
32
+ @backtrace = nil
33
+ @count = 1
34
+ @protected = false
35
+ @first_timestamp = nil
36
+ end
37
+
38
+ def to_h
39
+ h = {
40
+ message: @message,
41
+ progname: @progname,
42
+ severity: @severity,
43
+ timestamp: @timestamp,
44
+ key: @key,
45
+ backtrace: @backtrace,
46
+ count: @count,
47
+ env: @env,
48
+ protected: @protected
49
+ }
50
+
51
+ if @first_timestamp
52
+ h[:first_timestamp] = @first_timestamp
53
+ end
54
+
55
+ h
56
+ end
57
+
58
+ def to_json(opts = nil)
59
+ JSON.fast_generate(to_h, opts)
60
+ end
61
+
62
+ def self.from_json(json)
63
+ parsed = ::JSON.parse(json)
64
+ msg = new( parsed["severity"],
65
+ parsed["progname"],
66
+ parsed["message"],
67
+ parsed["timestamp"],
68
+ parsed["key"] )
69
+ msg.backtrace = parsed["backtrace"]
70
+ msg.env = parsed["env"]
71
+ msg.count = parsed["count"]
72
+ msg.protected = parsed["protected"]
73
+ msg.first_timestamp = parsed["first_timestamp"]
74
+ msg
75
+ end
76
+
77
+ def self.hostname
78
+ @hostname ||= `hostname`.strip! rescue "<unknown>"
79
+ end
80
+
81
+ def populate_from_env(env)
82
+ env ||= {}
83
+ @env = Message.populate_from_env(self.class.default_env.merge env)
84
+ end
85
+
86
+ def self.default_env
87
+ env = {
88
+ "hostname" => hostname,
89
+ "process_id" => Process.pid
90
+ }
91
+ env["application_version"] = Logster.config.application_version if Logster.config.application_version
92
+ env
93
+ end
94
+
95
+ # in its own method so it can be overridden
96
+ def grouping_hash
97
+ return { message: self.message, severity: self.severity, backtrace: self.backtrace }
98
+ end
99
+
100
+ # todo - memoize?
101
+ def grouping_key
102
+ Digest::SHA1.hexdigest JSON.fast_generate grouping_hash
103
+ end
104
+
105
+ # todo - memoize?
106
+ def solved_keys
107
+ if (versions=env["application_version"]) &&
108
+ (backtrace && backtrace.length > 0)
109
+ versions = [versions] if String === versions
110
+
111
+ versions.map do |version|
112
+ Digest::SHA1.hexdigest "#{version} #{backtrace}"
113
+ end
114
+ end
115
+ end
116
+
117
+ def is_similar?(other)
118
+ self.grouping_key == other.grouping_key
119
+ end
120
+
121
+ def merge_similar_message(other)
122
+ self.first_timestamp ||= self.timestamp
123
+ self.timestamp = [self.timestamp,other.timestamp].max
124
+ other_env = JSON.load JSON.fast_generate other.env
125
+ other_env.keys.each do |env_key|
126
+ self.env[env_key] = Message.env_merge_helper(self.env[env_key], other_env[env_key])
127
+ end
128
+ end
129
+
130
+ def self.populate_from_env(env)
131
+ env[LOGSTER_ENV] ||= begin
132
+ unless env.include? "rack.input"
133
+ # Not a web request
134
+ return env
135
+ end
136
+ scrubbed = default_env
137
+ request = Rack::Request.new(env)
138
+ params = {}
139
+ request.params.each do |k,v|
140
+ if k.include? "password"
141
+ params[k] = "[redacted]"
142
+ elsif Array === v
143
+ params[k] = v[0..20]
144
+ else
145
+ params[k] = v && v[0..100]
146
+ end
147
+ end
148
+ scrubbed["params"] = params if params.length > 0
149
+ ALLOWED_ENV.map{ |k|
150
+ scrubbed[k] = env[k] if env[k]
151
+ }
152
+ scrubbed
153
+ end
154
+ end
155
+
156
+ def <=>(other)
157
+ time = self.timestamp <=> other.timestamp
158
+ return time if time && time != 0
159
+
160
+ self.key <=> other.key
161
+ end
162
+
163
+ def =~(pattern)
164
+ case pattern
165
+ when Hash
166
+ IgnorePattern.new(nil, pattern).matches? self
167
+ when String
168
+ IgnorePattern.new(pattern, nil).matches? self
169
+ when Regexp
170
+ IgnorePattern.new(pattern, nil).matches? self
171
+ when IgnorePattern
172
+ pattern.matches? self
173
+ else
174
+ nil
175
+ end
176
+ end
177
+
178
+ protected
179
+
180
+ def get_timestamp
181
+ (Time.new.to_f * 1000).to_i
182
+ end
183
+
184
+ private
185
+
186
+ def self.env_merge_helper(self_value, other_value)
187
+ other_value = other_value.to_s if Symbol === other_value
188
+
189
+ if (Hash === self_value || self_value.nil?) && (Hash === other_value || other_value.nil?) && (!self_value.nil? || !other_value.nil?)
190
+ # one or both is a hash but not neither -> recurse on the keys
191
+ self_value = {} unless self_value
192
+ other_value = {} unless other_value
193
+ shared_keys = self_value.keys | (other_value.keys rescue [])
194
+ shared_keys.each do |key|
195
+ self_value[key] = env_merge_helper(self_value[key], other_value[key])
196
+ end
197
+ self_value
198
+ elsif self_value.is_a?(Array) && !other_value.is_a?(Array)
199
+ # Already have grouped data, so append to array (it's actually a set)
200
+ self_value << other_value unless self_value.include?(other_value) || self_value.length >= Logster::MAX_GROUPING_LENGTH
201
+ self_value
202
+ elsif !self_value.is_a?(Array)
203
+ if self_value == other_value
204
+ self_value
205
+ else
206
+ [self_value, other_value]
207
+ end
208
+ else
209
+ # They're both arrays.
210
+ # Three cases:
211
+ # self = [1,2,3] and other = [1,2,4] -> make into array of array
212
+ # self = [] and other = [1,2,4] -> make into array of array
213
+ # self = [[1,2,3], [1,2,5]] and other = [1,2,4] -> append to array
214
+ if self_value.length > 0 && self_value[0].is_a?(Array)
215
+ self_value << other_value unless self_value.include?(other_value) || self_value.length >= Logster::MAX_GROUPING_LENGTH
216
+ self_value
217
+ else
218
+ if self_value == other_value
219
+ self_value
220
+ else
221
+ [self_value, other_value]
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end