rack-reqorder 0.4.8 → 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f25501aa934652db3f5cc6a5683838a1b6bd1665
4
- data.tar.gz: 9c47d97e22515eac1bde1ad85bfcd259b77a7283
3
+ metadata.gz: a0d9d5b4fe1dadfe5ec2b8f248fb7862378ddd1b
4
+ data.tar.gz: 238cce079cb09e7ef03f9d11b756a5da73386557
5
5
  SHA512:
6
- metadata.gz: 0ee9d658036006d1bd825e7dbc94d1e22cb186682cc5fa31421e2f538c103a8e0e2e66e4a9b65ee82ba87cc4c9d9ff8839999d923673ceeb178d45c946940587
7
- data.tar.gz: 00241ea89a34078c7be449ffd537a5f14b181b6dbe79c7e94d02d4368904ffaaf7db1076150119def9155a2cd70aa25967fbcd33018276c07e087a6e1ce5f871
6
+ metadata.gz: b2c55e3216b4d70fc7fe3711b328781c5fad3e18526d545827d7163d150e9713cd871e8d9e7c2bf559b97075de58c0be47aff23a34261e5e1a3f33dc45ebc433
7
+ data.tar.gz: 91c820d63adea800dd5c5ad1fec1c6257da3c26728822ca3fc7da43ec962cf4c8a9aea65da4d1658634fa93c795a1d70694a3602900a32915211891584e41cfc
data/README.md CHANGED
@@ -4,12 +4,21 @@ Simple gem for monitoring Rack apps. Uses MongoDB. It can be used in combination
4
4
  with [rack-reqorder-monitor](https://github.com/kollegorna/rack-reqorder-monitor).
5
5
 
6
6
  ## Introduction
7
- Simple gem that sits on top of Rack and records request/response statistics
8
- as well as monitors for exceptions. It saves everything in MongoDB and exposes
9
- a simple API for retrieving these data.
7
+ Simple gem that sits on top of Rack and can:
8
+
9
+ - monitors for exceptions
10
+ - record full requests/responses, based on a header
11
+ - record request/response statistics
12
+
13
+ It saves everything in MongoDB and exposes simple API for retrieving these data.
10
14
 
11
15
  The API is very robust, built with the help of [mongoid_hash_query](https://github.com/kollegorna/mongoid_hash_query).
12
16
 
17
+ A simple, default, dashboard is build in ember can be found [here](https://github.com/kollegorna/rack-reqorder-monitor).
18
+
19
+ At the moment, Rails, Sinatra and Grape are supported.
20
+ We are looking forward to add support for Hanami (ex-lotus)
21
+
13
22
  ## Installation
14
23
 
15
24
  Add this line to your application's Gemfile:
@@ -44,20 +53,16 @@ end
44
53
 
45
54
  Rack::Reqorder.boot!
46
55
 
56
+ #if you run on development mode
47
57
  Rails.application.config.middleware.insert_after(ActionDispatch::DebugExceptions , Rack::Reqorder::Logger)
48
-
49
- #rack-cors also needed
50
- Rails.application.config.middleware.insert_before 0, "Rack::Cors" do
51
- allow do
52
- origins '*'
53
- resource '*', :headers => :any, :methods => [:get, :post, :options]
54
- end
55
- end
58
+ #or if run on production
59
+ #Rails.application.config.middleware.insert_after(0, Rack::Reqorder::Logger)
60
+ ```
61
+ Then in routes.rb enable the API for the [rack-reqorder-monitor](https://github.com/kollegorna/rack-reqorder-monitor).
62
+ ```ruby
63
+ require 'rack/reqorder/monitor'
64
+ mount Rack::Reqorder::Monitor::Api => '/rack-reqorder'
56
65
  ```
57
- Please note that you can configure origins and resource depending on how you
58
- mount the rack-monitor engine and where you deploy your front-end.
59
-
60
- For viewing your statistics please check [rack-reqorder-monitor](https://github.com/kollegorna/rack-reqorder-monitor)
61
66
 
62
67
  ## Development
63
68
 
@@ -67,7 +72,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
67
72
 
68
73
  ## Contributing
69
74
 
70
- 1. Fork it ( https://github.com/[my-github-username]/rack-reqorder/fork )
75
+ 1. Fork it ( https://github.com/kollegorna/rack-reqorder/fork )
71
76
  2. Create your feature branch (`git checkout -b my-new-feature`)
72
77
  3. Commit your changes (`git commit -am 'Add some feature'`)
73
78
  4. Push to the branch (`git push origin my-new-feature`)
@@ -2,6 +2,7 @@ require 'rack/reqorder/version'
2
2
  require 'active_support/inflector'
3
3
  require 'mongoid'
4
4
  require 'kaminari'
5
+ require 'rack/cors'
5
6
  require 'kaminari/models/mongoid_extension'
6
7
  require 'rack/reqorder/route_recognizers'
7
8
 
@@ -31,7 +32,7 @@ module Rack
31
32
 
32
33
  class Configuration
33
34
  attr_accessor :mongoid_yml, :environment, :auth_email, :auth_password,
34
- :no_auth
35
+ :no_auth, :metrics_monitoring, :exception_monitoring, :request_monitoring
35
36
 
36
37
  def validate!
37
38
  if mongoid_yml.blank?
@@ -42,18 +43,24 @@ module Rack
42
43
  self.environment = app_environment
43
44
  end
44
45
 
45
- self.auth_email = 'admin@example.com' if auth_email.blank?
46
- self.auth_password = 'password' if auth_password.blank?
47
- self.no_auth = false if self.no_auth.blank?
48
46
  end
49
47
 
50
48
  def app_environment
51
49
  if Module.const_defined?(:Rails)
52
50
  return Rails.env
53
51
  else
54
- return ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'staging'
52
+ return ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'unknown'
55
53
  end
56
54
  end
55
+
56
+ def initialize
57
+ self.auth_email = 'admin@example.com' if auth_email.blank?
58
+ self.auth_password = 'password' if auth_password.blank?
59
+ self.no_auth = false if self.no_auth.blank?
60
+ self.metrics_monitoring = true if self.metrics_monitoring.blank?
61
+ self.exception_monitoring = true if self.exception_monitoring.blank?
62
+ self.request_monitoring = true if self.request_monitoring.blank?
63
+ end
57
64
  end
58
65
  end
59
66
  end
@@ -75,9 +82,9 @@ require 'rack/reqorder/models/route_path'
75
82
  require 'rack/reqorder/models/http_response'
76
83
  require 'rack/reqorder/models/app_fault'
77
84
  require 'rack/reqorder/models/app_exception'
85
+ require 'rack/reqorder/models/recording'
78
86
  require 'rack/reqorder/services/backtrace_cleaner'
79
87
  require 'rack/reqorder/logger'
80
88
  require 'rack/reqorder/monitor'
81
89
 
82
90
  load 'rack/reqorder/tasks/routes.rake'
83
- load 'rack/reqorder/tasks/test_database.rake'
@@ -9,33 +9,57 @@ module Rack::Reqorder
9
9
  def call(environment)
10
10
  rack_request = Rack::Request.new(environment.clone)
11
11
 
12
+ http_request = record_request(rack_request) if conf.request_monitoring
13
+
12
14
  start = Time.now.to_f
13
15
  begin
14
16
  status, headers, body = @app.call(environment)
15
- response = Rack::Response.new(body, status, headers)
17
+ rack_response = Rack::Response.new(body, status, headers)
16
18
  rescue => exception
17
- response = log_exception(exception, environment)
19
+ rack_response = log_exception(exception, rack_request) if conf.exception_monitoring
20
+
18
21
  raise exception
19
22
  ensure
20
- response_time = Time.now.to_f - start
21
-
22
- if response
23
- save_statistics(
24
- rack_request: rack_request,
25
- rack_response: response,
26
- response_time: response_time
27
- )
28
- end
23
+ record_statistics(rack_request, rack_response, Time.now.to_f - start)
29
24
  end
25
+ record_response(rack_response, http_request) if conf.request_monitoring
30
26
 
31
27
  return [status, headers, body]
32
28
  end
33
29
 
34
30
  private
31
+ def record_statistics(rack_request, rack_response, response_time)
32
+ if rack_response && conf.metrics_monitoring
33
+ save_statistics(
34
+ rack_request: rack_request,
35
+ rack_response: rack_response,
36
+ response_time: response_time
37
+ )
38
+ end
39
+ end
40
+
41
+ def record_request(rack_request)
42
+ request_headers = extract_all_headers(rack_request.env)
43
+ recording = nil
44
+
45
+ Recording.enabled.all.each do |rec|
46
+ if request_headers[rec.http_header] == rec.http_header_value
47
+ recording = rec and break
48
+ end
49
+ end
50
+
51
+ return save_http_request(rack_request, recording)
52
+ end
35
53
 
36
- def extract_all_headers(request)
54
+ def record_response(rack_response, http_request)
55
+ if http_request && http_request.recording
56
+ return save_http_response(rack_response, http_request)
57
+ end
58
+ end
59
+
60
+ def extract_all_headers(env)
37
61
  Hash[
38
- request.env.select{|k,v|
62
+ env.select{|k,v|
39
63
  k.start_with? 'HTTP_'
40
64
  }.map{|k,v|
41
65
  [k.gsub('HTTP_','').upcase, v]
@@ -90,44 +114,46 @@ module Rack::Reqorder
90
114
  end
91
115
  end
92
116
 
93
- def save_http_request(environment)
94
- request = Rack::Request.new(environment)
95
117
 
96
- route_path = RoutePath.find_or_create_by({
97
- route: Rack::Reqorder.recognize_path(request.path),
98
- http_method: request.request_method
99
- })
118
+ def save_http_request(rack_request, recording = nil)
119
+ if not recording
120
+ route_path = RoutePath.find_or_create_by({
121
+ route: Rack::Reqorder.recognize_path(rack_request.path),
122
+ http_method: rack_request.request_method
123
+ })
124
+ end
100
125
 
101
126
  HttpRequest.create({
102
- ip: request.ip,
103
- url: request.url,
104
- scheme: request.scheme,
105
- base_url: request.base_url,
106
- port: request.port,
107
- path: request.path,
108
- full_path: request.fullpath,
109
- http_method: request.request_method,
110
- headers: extract_all_headers(request),
111
- params: request.params,
112
- ssl: request.ssl?,
113
- xhr: request.xhr?,
114
- route_path: route_path
127
+ ip: rack_request.ip,
128
+ url: rack_request.url,
129
+ scheme: rack_request.scheme,
130
+ base_url: rack_request.base_url,
131
+ port: rack_request.port,
132
+ path: rack_request.path,
133
+ full_path: rack_request.fullpath,
134
+ http_method: rack_request.request_method,
135
+ headers: extract_all_headers(rack_request.env),
136
+ params: rack_request.params,
137
+ ssl: rack_request.ssl?,
138
+ xhr: rack_request.xhr?,
139
+ route_path: recording ? nil : route_path,
140
+ recording: recording ? recording : nil
115
141
  })
116
142
  end
117
143
 
118
- def save_http_response(body, status, headers, http_request)
119
- response = Rack::Response.new(body, status, headers)
120
-
144
+ def save_http_response(rack_response, http_request)
121
145
  HttpResponse.create(
122
- headers: response.headers,
123
- #body: response.body.first,
124
- status: response.status.to_i,
125
- http_request: http_request
146
+ headers: rack_response.headers,
147
+ body: rack_response.body.first,
148
+ status: rack_response.status.to_i,
149
+ length: rack_response.length,
150
+ http_request: http_request,
151
+ recording: http_request.recording.nil? ? nil : http_request.recording
126
152
  )
127
153
  end
128
154
 
129
- def log_exception(exception, environment)
130
- http_request = save_http_request(environment)
155
+ def log_exception(exception, rack_request)
156
+ http_request = save_http_request(rack_request)
131
157
 
132
158
  bc = BacktraceCleaner.new
133
159
  bc.add_filter { |line| line.gsub(Rails.root.to_s, '') }
@@ -147,7 +173,7 @@ module Rack::Reqorder
147
173
  e_class: exception.class,
148
174
  line: line.to_i,
149
175
  filepath: path[1..-1],
150
- environment: app_environment
176
+ environment: conf.environment
151
177
  )
152
178
 
153
179
  AppException.create(
@@ -181,12 +207,8 @@ module Rack::Reqorder
181
207
  end
182
208
  end
183
209
 
184
- def app_environment
185
- if Module.const_defined?(:Rails)
186
- return Rails.env
187
- else
188
- return ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'unknown'
189
- end
210
+ def conf
211
+ Rack::Reqorder.configuration
190
212
  end
191
213
  end
192
214
  end
@@ -8,6 +8,8 @@ module Rack::Reqorder::Models
8
8
  field :line, type: Integer
9
9
  field :filepath, type: String
10
10
 
11
+ field :last_seen_at, type: Time
12
+
11
13
  field :resolved, type: Boolean, default: false
12
14
 
13
15
  field :environment, type: String
@@ -18,7 +20,9 @@ module Rack::Reqorder::Models
18
20
 
19
21
  def update_count!
20
22
  self.app_exceptions_count = self.app_exceptions.count
23
+ self.last_seen_at = DateTime.now
21
24
  self.save!
22
25
  end
26
+
23
27
  end
24
28
  end
@@ -23,11 +23,17 @@ module Rack::Reqorder::Models
23
23
  has_one :app_exception, dependent: :destroy
24
24
 
25
25
  belongs_to :route_path, dependent: :nullify
26
+ belongs_to :recording, dependent: :nullify
26
27
 
27
28
  before_create :add_param_keys
29
+ after_save :update_recording_requests_count, if: :recording_id
28
30
  private
29
31
  def add_param_keys
30
32
  self.param_keys = self.params.keys
31
33
  end
34
+
35
+ def update_recording_requests_count
36
+ self.recording.update_requests_count!
37
+ end
32
38
  end
33
39
  end
@@ -6,10 +6,12 @@ module Rack::Reqorder::Models
6
6
 
7
7
  field :headers, type: Hash
8
8
  field :status, type: Integer
9
- #field :body, type: String
9
+ field :body, type: String
10
+ field :length, type: Integer
10
11
  field :response_time, type: Float
11
12
 
12
13
  belongs_to :http_request, dependent: :nullify
14
+ belongs_to :recording, dependent: :nullify
13
15
 
14
16
  before_create :set_response_time
15
17
  after_create :set_response_time_to_request
@@ -0,0 +1,22 @@
1
+ module Rack::Reqorder::Models
2
+ class Recording
3
+ include ::Mongoid::Document
4
+ include ::Kaminari::MongoidExtension::Document
5
+ include ::Mongoid::Timestamps
6
+
7
+ field :http_header, type: String
8
+ field :http_header_value, type: String
9
+ field :enabled, type: Boolean, default: true
10
+ field :requests_count, type: Integer, default: 0
11
+
12
+ has_many :http_requests, dependent: :nullify
13
+ has_many :http_responses, dependent: :nullify
14
+
15
+ scope :enabled, -> {where(enabled: true)}
16
+
17
+ def update_requests_count!
18
+ self.requests_count = self.http_requests.count
19
+ self.save!
20
+ end
21
+ end
22
+ end
@@ -24,11 +24,14 @@ module Rack::Reqorder::Monitor
24
24
  format :json
25
25
  prefix :api
26
26
 
27
- =begin
28
27
  rescue_from Grape::Exceptions::ValidationErrors do |e|
29
28
  error!({errors: e.send(:full_messages)}, 422)
30
29
  end
31
- =end
30
+
31
+ before do
32
+ header 'Access-Control-Allow-Origin', '*'
33
+ header 'Access-Control-Allow-Methods', '*'
34
+ end
32
35
 
33
36
  #collection routes
34
37
  resource :route_paths do
@@ -50,6 +53,15 @@ module Rack::Reqorder::Monitor
50
53
  )
51
54
  end
52
55
 
56
+ delete do
57
+ route_paths = RoutePath.delete_all
58
+
59
+ present_with_meta(
60
+ route_paths,
61
+ present(route_paths, with: RoutePathEntity)
62
+ )
63
+ end
64
+
53
65
  #element routes
54
66
  route_param :id do
55
67
  get do
@@ -89,6 +101,15 @@ module Rack::Reqorder::Monitor
89
101
  )
90
102
  end
91
103
 
104
+ delete do
105
+ requests = HttpRequest.delete_all
106
+
107
+ present_with_meta(
108
+ requests,
109
+ present(requests, with: RequestEntity)
110
+ )
111
+ end
112
+
92
113
  #element routes
93
114
  route_param :id do
94
115
  get do
@@ -119,6 +140,15 @@ module Rack::Reqorder::Monitor
119
140
  )
120
141
  end
121
142
 
143
+ delete do
144
+ responses = HttpResponse.delete_all
145
+
146
+ present_with_meta(
147
+ responses,
148
+ present(responses, with: ResponseEntity)
149
+ )
150
+ end
151
+
122
152
  #element routes
123
153
  route_param :id do
124
154
  get do
@@ -151,6 +181,16 @@ module Rack::Reqorder::Monitor
151
181
  )
152
182
  end
153
183
 
184
+ delete do
185
+ faults = AppFault.delete_all
186
+
187
+ present_with_meta(
188
+ faults,
189
+ present(faults, with: FaultEntity)
190
+ )
191
+
192
+ end
193
+
154
194
  #element routes
155
195
  route_param :id do
156
196
  get do
@@ -194,6 +234,15 @@ module Rack::Reqorder::Monitor
194
234
  )
195
235
  end
196
236
 
237
+ delete do
238
+ exceptions = AppException.delete_all
239
+
240
+ present_with_meta(
241
+ exceptions,
242
+ present(exceptions, with: ExceptionEntity)
243
+ )
244
+ end
245
+
197
246
  #element routes
198
247
  route_param :id do
199
248
  get do
@@ -202,6 +251,56 @@ module Rack::Reqorder::Monitor
202
251
  end
203
252
  end
204
253
 
254
+ #collection routes
255
+ resource :recordings do
256
+ before do
257
+ authorize_user!(headers) unless Rack::Reqorder.configuration.no_auth
258
+ end
259
+
260
+ get do
261
+ recordings = apply_filters(Recording.all, params)
262
+
263
+ meta_aggregations = aggregations(recordings, params)
264
+
265
+ recordings = paginate(recordings, params)
266
+
267
+ present_with_meta(
268
+ recordings,
269
+ present(recordings, with: RecordingEntity),
270
+ meta_aggregations
271
+ )
272
+ end
273
+
274
+ params do
275
+ requires :recording, type: Hash do
276
+ requires :http_header, type: String
277
+ requires :http_header_value, type: String
278
+ end
279
+ end
280
+ post do
281
+ present(
282
+ Recording.create!({
283
+ http_header: declared(params)[:recording][:http_header],
284
+ http_header_value: declared(params)[:recording][:http_header_value]
285
+ }),
286
+ with: RecordingEntity
287
+ )
288
+ end
289
+
290
+ #element routes
291
+ route_param :id do
292
+ get do
293
+ present(Recording.find(params[:id]), with: RecordingEntity)
294
+ end
295
+
296
+ delete do
297
+ recording = Recording.find(params[:id])
298
+ recording.destroy
299
+
300
+ present(recording, with: RecordingEntity)
301
+ end
302
+ end
303
+ end
205
304
 
206
305
  params do
207
306
  requires :user, type: Hash do
@@ -124,6 +124,7 @@ module Rack::Reqorder::Monitor
124
124
 
125
125
  with_options(format_with: :association_id) do
126
126
  expose :http_response, as: :response_id
127
+ expose :recording, as: :recording_id
127
128
  end
128
129
 
129
130
  end
@@ -133,6 +134,7 @@ module Rack::Reqorder::Monitor
133
134
 
134
135
  expose :headers
135
136
  expose :status
137
+ expose :body
136
138
  expose :response_time
137
139
 
138
140
  with_options(format_with: :iso_timestamp) do
@@ -142,6 +144,7 @@ module Rack::Reqorder::Monitor
142
144
 
143
145
  with_options(format_with: :association_id) do
144
146
  expose :http_request, as: :request_id
147
+ expose :recording, as: :recording_id
145
148
  end
146
149
  end
147
150
 
@@ -163,6 +166,7 @@ module Rack::Reqorder::Monitor
163
166
  end
164
167
 
165
168
  with_options(format_with: :iso_timestamp) do
169
+ expose :last_seen_at
166
170
  expose :created_at
167
171
  expose :updated_at
168
172
  end
@@ -187,7 +191,20 @@ module Rack::Reqorder::Monitor
187
191
  expose :http_request, as: :request_id
188
192
  expose :app_fault, as: :fault_id
189
193
  end
194
+ end
195
+
196
+ class RecordingEntity < BaseEntity
197
+ root :recordings, :recording
190
198
 
199
+ expose :http_header
200
+ expose :http_header_value
201
+ expose :enabled
202
+ expose :requests_count
203
+
204
+ with_options(format_with: :iso_timestamp) do
205
+ expose :created_at
206
+ expose :updated_at
207
+ end
191
208
  end
192
209
 
193
210
  class SessionEntity < Grape::Entity
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Reqorder
3
- VERSION = "0.4.8"
3
+ VERSION = "0.5"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-reqorder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.8
4
+ version: '0.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Filippos Vasilakis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-10-27 00:00:00.000000000 Z
12
+ date: 2016-04-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -218,6 +218,7 @@ files:
218
218
  - lib/rack/reqorder/models/app_fault.rb
219
219
  - lib/rack/reqorder/models/http_request.rb
220
220
  - lib/rack/reqorder/models/http_response.rb
221
+ - lib/rack/reqorder/models/recording.rb
221
222
  - lib/rack/reqorder/models/route_path.rb
222
223
  - lib/rack/reqorder/models/statistic.rb
223
224
  - lib/rack/reqorder/monitor.rb
@@ -226,7 +227,6 @@ files:
226
227
  - lib/rack/reqorder/route_recognizers.rb
227
228
  - lib/rack/reqorder/services/backtrace_cleaner.rb
228
229
  - lib/rack/reqorder/tasks/routes.rake
229
- - lib/rack/reqorder/tasks/test_database.rake
230
230
  - lib/rack/reqorder/version.rb
231
231
  - rack-reqorder.gemspec
232
232
  homepage: https://github.com/kollegorna/rack-reqorder
@@ -1,29 +0,0 @@
1
- if respond_to?(:namespace, true)
2
- namespace 'rack-reqorder' do
3
- desc 'rack-monitor API routes'
4
- task :test_database => :environment do
5
- env = ENV["RACK_ENV"] || ENV["RAILS_ENV"] || Rails.env
6
- return 'Available only under development env' unless env == 'development'
7
-
8
- require_relative '../../../../spec/rack/factories/statistics.rb'
9
- require_relative '../../../../spec/rack/factories/route_paths.rb'
10
- require_relative '../../../../spec/rack/factories/app_faults.rb'
11
-
12
- 10.times { FactoryGirl.create(:route_path) }
13
-
14
- FactoryGirl.create(
15
- :route_path,
16
- route: '/rack-reqorder/api/v1/route_path_24_statistics',
17
- http_method: 'GET'
18
- )
19
-
20
- FactoryGirl.create(
21
- :route_path,
22
- route: '/rack-reqorder/api/v1/route_paths',
23
- http_method: 'GET'
24
- )
25
-
26
- 40.times { FactoryGirl.create(:app_fault) }
27
- end
28
- end
29
- end