logster 1.3.0 → 1.3.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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -18
  3. data/.travis.yml +15 -15
  4. data/CHANGELOG.md +137 -130
  5. data/Gemfile +4 -4
  6. data/Guardfile +8 -8
  7. data/LICENSE.txt +22 -22
  8. data/README.md +99 -99
  9. data/Rakefile +24 -24
  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 -81
  21. data/assets/javascript/vendor.js +5302 -5302
  22. data/assets/stylesheets/client-app.css +0 -0
  23. data/assets/stylesheets/vendor.css +3 -3
  24. data/build_client_app.sh +12 -12
  25. data/client-app/.editorconfig +20 -20
  26. data/client-app/.ember-cli +9 -9
  27. data/client-app/.eslintignore +19 -19
  28. data/client-app/.eslintrc.js +46 -46
  29. data/client-app/.gitignore +23 -23
  30. data/client-app/.travis.yml +27 -27
  31. data/client-app/.watchmanconfig +3 -3
  32. data/client-app/README.md +57 -57
  33. data/client-app/app/app.js +14 -14
  34. data/client-app/app/components/message-info.js +18 -18
  35. data/client-app/app/components/message-row.js +45 -45
  36. data/client-app/app/components/panel-resizer.js +75 -75
  37. data/client-app/app/components/tab-contents.js +27 -27
  38. data/client-app/app/components/tab-link.js +5 -5
  39. data/client-app/app/components/tabbed-section.js +32 -32
  40. data/client-app/app/components/time-formatter.js +25 -25
  41. data/client-app/app/components/update-time.js +21 -21
  42. data/client-app/app/controllers/index.js +83 -83
  43. data/client-app/app/controllers/show.js +13 -13
  44. data/client-app/app/index.html +29 -29
  45. data/client-app/app/initializers/app-init.js +55 -55
  46. data/client-app/app/lib/preload.js +14 -14
  47. data/client-app/app/lib/utilities.js +140 -140
  48. data/client-app/app/models/message-collection.js +158 -158
  49. data/client-app/app/models/message.js +99 -99
  50. data/client-app/app/resolver.js +3 -3
  51. data/client-app/app/router.js +14 -14
  52. data/client-app/app/routes/index.js +53 -53
  53. data/client-app/app/routes/show.js +14 -14
  54. data/client-app/app/styles/app.css +387 -387
  55. data/client-app/app/templates/application.hbs +2 -2
  56. data/client-app/app/templates/components/message-info.hbs +44 -44
  57. data/client-app/app/templates/components/message-row.hbs +17 -17
  58. data/client-app/app/templates/components/tabbed-section.hbs +10 -10
  59. data/client-app/app/templates/components/time-formatter.hbs +1 -1
  60. data/client-app/app/templates/index.hbs +57 -57
  61. data/client-app/app/templates/show.hbs +4 -4
  62. data/client-app/config/environment.js +51 -51
  63. data/client-app/config/optional-features.json +3 -3
  64. data/client-app/config/targets.js +18 -18
  65. data/client-app/ember-cli-build.js +29 -29
  66. data/client-app/package-lock.json +11365 -11365
  67. data/client-app/package.json +56 -56
  68. data/client-app/testem.js +25 -25
  69. data/client-app/tests/index.html +34 -34
  70. data/client-app/tests/integration/components/message-info-test.js +26 -26
  71. data/client-app/tests/integration/components/message-row-test.js +26 -26
  72. data/client-app/tests/integration/components/panel-resizer-test.js +26 -26
  73. data/client-app/tests/integration/components/tab-contents-test.js +26 -26
  74. data/client-app/tests/integration/components/tab-link-test.js +26 -26
  75. data/client-app/tests/integration/components/tabbed-section-test.js +26 -26
  76. data/client-app/tests/integration/components/time-formatter-test.js +26 -26
  77. data/client-app/tests/integration/components/update-time-test.js +26 -26
  78. data/client-app/tests/test-helper.js +8 -8
  79. data/client-app/tests/unit/controllers/index-test.js +12 -12
  80. data/client-app/tests/unit/controllers/show-test.js +12 -12
  81. data/client-app/tests/unit/initializers/app-init-test.js +31 -31
  82. data/client-app/tests/unit/routes/index-test.js +11 -11
  83. data/client-app/tests/unit/routes/show-test.js +11 -11
  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 +108 -102
  90. data/lib/logster/message.rb +227 -227
  91. data/lib/logster/middleware/debug_exceptions.rb +26 -26
  92. data/lib/logster/middleware/reporter.rb +56 -56
  93. data/lib/logster/middleware/viewer.rb +220 -220
  94. data/lib/logster/rails/railtie.rb +58 -58
  95. data/lib/logster/redis_store.rb +481 -481
  96. data/lib/logster/version.rb +3 -3
  97. data/lib/logster/web.rb +14 -14
  98. data/logster.gemspec +34 -34
  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 -96
  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 +80 -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 -427
  110. data/test/test_helper.rb +38 -38
  111. data/vendor/assets/javascripts/logster.js.erb +39 -39
  112. metadata +3 -3
@@ -1,227 +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
- @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
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