rack-reqorder 0.3.0 → 0.4.0
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 +4 -4
- data/Gemfile +0 -3
- data/README.md +9 -1
- data/lib/rack/reqorder.rb +12 -17
- data/lib/rack/reqorder/logger.rb +38 -16
- data/lib/rack/reqorder/models/app_fault.rb +5 -0
- data/lib/rack/reqorder/models/route_path.rb +6 -26
- data/lib/rack/reqorder/models/statistic.rb +5 -1
- data/lib/rack/reqorder/monitor.rb +80 -10
- data/lib/rack/reqorder/monitor/entities.rb +76 -1
- data/lib/rack/reqorder/monitor/helpers.rb +92 -0
- data/lib/rack/reqorder/route_recognizers.rb +156 -0
- data/lib/rack/reqorder/tasks/routes.rake +1 -1
- data/lib/rack/reqorder/tasks/test_database.rake +29 -0
- data/lib/rack/reqorder/version.rb +1 -1
- data/rack-reqorder.gemspec +8 -4
- metadata +69 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92a69c99b0738479b0b998e1a7f7c5d3f3051f46
|
4
|
+
data.tar.gz: 7e032e5347593d459db3e183dd1b1cb653d91b7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b80ff10e5dfb1ff79ae7f5233b495f62f2e63374528e31742614e4b1f34b2501c4a44399c8d7655e0e65cc9b2efa845040b2f302c49d2a621290328b0889a08
|
7
|
+
data.tar.gz: f732af69470fb3123ada1da63fb932d68863832c53901fbe2ef98441a3d36256bb90bf49a20ff7fa60c0b00772665ee9ffc3ef993c33bb1fb967a3ff59cce71d
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -27,7 +27,13 @@ Or install it yourself as:
|
|
27
27
|
$ gem install rack-reqorder
|
28
28
|
|
29
29
|
## Usage
|
30
|
-
|
30
|
+
You first need to initialize mongoid/mongodb by running:
|
31
|
+
|
32
|
+
```bash
|
33
|
+
bundle exec rails g mongoid:config
|
34
|
+
```
|
35
|
+
|
36
|
+
Then just add it on the middleware pipeline and initialize it.
|
31
37
|
|
32
38
|
For instance, in Rails, in an initializer add:
|
33
39
|
|
@@ -51,6 +57,8 @@ end
|
|
51
57
|
Please note that you can configure origins and resource depending on how you
|
52
58
|
mount the rack-monitor engine and where you deploy your front-end.
|
53
59
|
|
60
|
+
For viewing your statistics please check [rack-reqorder-monitor](https://github.com/kollegorna/rack-reqorder-monitor)
|
61
|
+
|
54
62
|
## Development
|
55
63
|
|
56
64
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/rack/reqorder.rb
CHANGED
@@ -3,9 +3,14 @@ require 'active_support/inflector'
|
|
3
3
|
require 'mongoid'
|
4
4
|
require 'kaminari'
|
5
5
|
require 'kaminari/models/mongoid_extension'
|
6
|
+
require 'rack/reqorder/route_recognizers'
|
6
7
|
|
7
8
|
module Rack
|
8
9
|
module Reqorder
|
10
|
+
extend Rack::Reqorder::GrapeRecognizer
|
11
|
+
extend Rack::Reqorder::SinatraRecognizer
|
12
|
+
extend Rack::Reqorder::RailsRecognizer
|
13
|
+
|
9
14
|
class << self
|
10
15
|
attr_accessor :configuration
|
11
16
|
end
|
@@ -24,24 +29,9 @@ module Rack
|
|
24
29
|
)
|
25
30
|
end
|
26
31
|
|
27
|
-
def self.paths
|
28
|
-
return @paths unless @paths.blank?
|
29
|
-
@paths = {}
|
30
|
-
Rails.application.routes.routes.routes.each do |route|
|
31
|
-
@paths[route.defaults] = route.path.spec.left.to_s
|
32
|
-
end
|
33
|
-
|
34
|
-
return @paths
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.recognise_path(path_uri, options = {})
|
38
|
-
res = Rack::Reqorder.paths[Rails.application.routes.recognize_path(path_uri, options)
|
39
|
-
.select{|key, value| [:action, :controller].include?(key)}
|
40
|
-
]
|
41
|
-
end
|
42
|
-
|
43
32
|
class Configuration
|
44
|
-
attr_accessor :mongoid_yml, :environment
|
33
|
+
attr_accessor :mongoid_yml, :environment, :auth_email, :auth_password,
|
34
|
+
:no_auth
|
45
35
|
|
46
36
|
def validate!
|
47
37
|
if mongoid_yml.blank?
|
@@ -52,6 +42,10 @@ module Rack
|
|
52
42
|
puts 'rack-reqorder: No environment found, assuming development environment'
|
53
43
|
self.environment = :development
|
54
44
|
end
|
45
|
+
|
46
|
+
self.auth_email = 'admin@example.com' if auth_email.blank?
|
47
|
+
self.auth_password = 'password' if auth_password.blank?
|
48
|
+
self.no_auth = false if self.no_auth.blank?
|
55
49
|
end
|
56
50
|
end
|
57
51
|
end
|
@@ -79,3 +73,4 @@ require 'rack/reqorder/logger'
|
|
79
73
|
require 'rack/reqorder/monitor'
|
80
74
|
|
81
75
|
load 'rack/reqorder/tasks/routes.rake'
|
76
|
+
load 'rack/reqorder/tasks/test_database.rake'
|
data/lib/rack/reqorder/logger.rb
CHANGED
@@ -7,23 +7,24 @@ module Rack::Reqorder
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def call(environment)
|
10
|
-
|
10
|
+
rack_request = Rack::Request.new(environment.clone)
|
11
11
|
|
12
12
|
start = Time.now.to_f
|
13
13
|
begin
|
14
14
|
status, headers, body = @app.call(environment)
|
15
|
+
response = Rack::Response.new(body, status, headers)
|
15
16
|
rescue => exception
|
16
|
-
log_exception(exception, environment)
|
17
|
+
response = log_exception(exception, environment)
|
17
18
|
raise exception
|
19
|
+
ensure
|
20
|
+
response_time = Time.now.to_f - start
|
21
|
+
|
22
|
+
save_statistics(
|
23
|
+
rack_request: rack_request,
|
24
|
+
rack_response: response,
|
25
|
+
response_time: response_time
|
26
|
+
)
|
18
27
|
end
|
19
|
-
response_time = Time.now.to_f - start
|
20
|
-
|
21
|
-
#save_http_response(body, status, headers, http_request)
|
22
|
-
save_statistics(
|
23
|
-
rack_request: Rack::Request.new(environment),
|
24
|
-
rack_response: Rack::Response.new(body, status, headers),
|
25
|
-
response_time: response_time
|
26
|
-
)
|
27
28
|
|
28
29
|
return [status, headers, body]
|
29
30
|
end
|
@@ -42,15 +43,27 @@ module Rack::Reqorder
|
|
42
43
|
]
|
43
44
|
end
|
44
45
|
|
46
|
+
def route_template(request_path:, request_method:)
|
47
|
+
Rack::Reqorder.recognize_path(request_path, {method: request_method})
|
48
|
+
end
|
49
|
+
|
45
50
|
def save_statistics(rack_request:, rack_response:, response_time:)
|
46
51
|
route_path = RoutePath.find_or_create_by({
|
47
|
-
route:
|
52
|
+
route: route_template({
|
53
|
+
#response_status: rack_response.status,
|
54
|
+
request_path: rack_request.path,
|
55
|
+
request_method: rack_request.request_method
|
56
|
+
}),
|
48
57
|
http_method: rack_request.request_method
|
49
58
|
})
|
50
59
|
|
51
|
-
[:all.to_s, DateTime.now.hour.to_s].each do |key|
|
60
|
+
[:all.to_s, DateTime.now.utc.hour.to_s].each do |key|
|
52
61
|
statistic = route_path.send("statistic_#{key}".to_sym)
|
53
62
|
|
63
|
+
if key != :all && statistic && statistic.created_at.to_date < DateTime.now.utc.to_date
|
64
|
+
statistic = route_path.send("create_statistic_#{key}")
|
65
|
+
end
|
66
|
+
|
54
67
|
if statistic.nil?
|
55
68
|
statistic = route_path.send("create_statistic_#{key}")
|
56
69
|
end
|
@@ -79,7 +92,7 @@ module Rack::Reqorder
|
|
79
92
|
request = Rack::Request.new(environment)
|
80
93
|
|
81
94
|
route_path = RoutePath.find_or_create_by({
|
82
|
-
route: Rack::Reqorder.
|
95
|
+
route: Rack::Reqorder.recognize_path(request.path),
|
83
96
|
http_method: request.request_method
|
84
97
|
})
|
85
98
|
|
@@ -128,11 +141,12 @@ module Rack::Reqorder
|
|
128
141
|
path, line, _ = exception.backtrace.first.split(':')
|
129
142
|
end
|
130
143
|
|
131
|
-
|
132
144
|
app_fault = AppFault.find_or_create_by(
|
133
145
|
e_class: exception.class,
|
134
146
|
line: line.to_i,
|
135
|
-
filepath: path[1..-1]
|
147
|
+
filepath: path[1..-1],
|
148
|
+
route_path: http_request.route_path,
|
149
|
+
environment: app_environment
|
136
150
|
)
|
137
151
|
|
138
152
|
AppException.create(
|
@@ -147,7 +161,7 @@ module Rack::Reqorder
|
|
147
161
|
http_request: http_request
|
148
162
|
)
|
149
163
|
|
150
|
-
HttpResponse.create(
|
164
|
+
return HttpResponse.create(
|
151
165
|
status: 500,
|
152
166
|
http_request: http_request
|
153
167
|
)
|
@@ -165,5 +179,13 @@ module Rack::Reqorder
|
|
165
179
|
end
|
166
180
|
end
|
167
181
|
end
|
182
|
+
|
183
|
+
def app_environment
|
184
|
+
if Module.const_defined?(:Rails)
|
185
|
+
return Rails.env
|
186
|
+
else
|
187
|
+
return ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'unknown'
|
188
|
+
end
|
189
|
+
end
|
168
190
|
end
|
169
191
|
end
|
@@ -8,8 +8,13 @@ module Rack::Reqorder::Models
|
|
8
8
|
field :line, type: Integer
|
9
9
|
field :filepath, type: String
|
10
10
|
|
11
|
+
field :resolved, type: Boolean, default: false
|
12
|
+
|
13
|
+
field :environment, type: String
|
14
|
+
|
11
15
|
field :app_exceptions_count, type: Integer, default: 0
|
12
16
|
|
17
|
+
belongs_to :route_path, dependent: :nullify
|
13
18
|
has_many :app_exceptions, dependent: :destroy
|
14
19
|
|
15
20
|
def update_count!
|
@@ -9,32 +9,12 @@ module Rack::Reqorder::Models
|
|
9
9
|
|
10
10
|
has_many :http_requests, dependent: :destroy
|
11
11
|
|
12
|
-
embeds_one :statistic_0, class_name: 'Rack::Reqorder::Models::Statistic'
|
13
|
-
embeds_one :statistic_1, class_name: 'Rack::Reqorder::Models::Statistic'
|
14
|
-
embeds_one :statistic_2, class_name: 'Rack::Reqorder::Models::Statistic'
|
15
|
-
embeds_one :statistic_3, class_name: 'Rack::Reqorder::Models::Statistic'
|
16
|
-
embeds_one :statistic_4, class_name: 'Rack::Reqorder::Models::Statistic'
|
17
|
-
embeds_one :statistic_5, class_name: 'Rack::Reqorder::Models::Statistic'
|
18
|
-
embeds_one :statistic_6, class_name: 'Rack::Reqorder::Models::Statistic'
|
19
|
-
embeds_one :statistic_7, class_name: 'Rack::Reqorder::Models::Statistic'
|
20
|
-
embeds_one :statistic_8, class_name: 'Rack::Reqorder::Models::Statistic'
|
21
|
-
embeds_one :statistic_9, class_name: 'Rack::Reqorder::Models::Statistic'
|
22
|
-
embeds_one :statistic_10, class_name: 'Rack::Reqorder::Models::Statistic'
|
23
|
-
embeds_one :statistic_11, class_name: 'Rack::Reqorder::Models::Statistic'
|
24
|
-
embeds_one :statistic_12, class_name: 'Rack::Reqorder::Models::Statistic'
|
25
|
-
embeds_one :statistic_13, class_name: 'Rack::Reqorder::Models::Statistic'
|
26
|
-
embeds_one :statistic_14, class_name: 'Rack::Reqorder::Models::Statistic'
|
27
|
-
embeds_one :statistic_15, class_name: 'Rack::Reqorder::Models::Statistic'
|
28
|
-
embeds_one :statistic_16, class_name: 'Rack::Reqorder::Models::Statistic'
|
29
|
-
embeds_one :statistic_17, class_name: 'Rack::Reqorder::Models::Statistic'
|
30
|
-
embeds_one :statistic_18, class_name: 'Rack::Reqorder::Models::Statistic'
|
31
|
-
embeds_one :statistic_19, class_name: 'Rack::Reqorder::Models::Statistic'
|
32
|
-
embeds_one :statistic_20, class_name: 'Rack::Reqorder::Models::Statistic'
|
33
|
-
embeds_one :statistic_21, class_name: 'Rack::Reqorder::Models::Statistic'
|
34
|
-
embeds_one :statistic_22, class_name: 'Rack::Reqorder::Models::Statistic'
|
35
|
-
embeds_one :statistic_23, class_name: 'Rack::Reqorder::Models::Statistic'
|
36
|
-
embeds_one :statistic_24, class_name: 'Rack::Reqorder::Models::Statistic'
|
37
|
-
|
38
12
|
embeds_one :statistic_all, class_name: 'Rack::Reqorder::Models::Statistic'
|
13
|
+
|
14
|
+
0.upto(23) do |i|
|
15
|
+
embeds_one "statistic_#{i}", class_name: 'Rack::Reqorder::Models::Statistic'
|
16
|
+
end
|
17
|
+
|
18
|
+
has_one :app_fault, dependent: :destroy
|
39
19
|
end
|
40
20
|
end
|
@@ -20,7 +20,11 @@ module Rack::Reqorder::Models
|
|
20
20
|
field :xhr_count, type: Integer, default: 0
|
21
21
|
field :ssl_count, type: Integer, default: 0
|
22
22
|
|
23
|
-
embedded_in :route_path
|
23
|
+
embedded_in :route_path, inverse_of: :statistic_all
|
24
|
+
|
25
|
+
0.upto(23) do |i|
|
26
|
+
embedded_in :route_path, inverse_of: "statistic_#{i}"
|
27
|
+
end
|
24
28
|
|
25
29
|
def recalculate_average!(response_time)
|
26
30
|
self.avg_response_time = (
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'grape'
|
2
2
|
require 'grape-entity'
|
3
|
+
require 'rack/reqorder/monitor/helpers'
|
3
4
|
require 'rack/reqorder/monitor/entities'
|
4
5
|
require 'mongoid_hash_query'
|
5
6
|
require 'pry'
|
@@ -10,20 +11,32 @@ module Rack::Reqorder
|
|
10
11
|
end
|
11
12
|
|
12
13
|
module Rack::Reqorder::Monitor
|
14
|
+
|
13
15
|
class Api < Grape::API
|
14
16
|
include Rack::Reqorder::Models
|
15
17
|
include Rack::Reqorder::Monitor::Entities
|
16
18
|
|
17
19
|
helpers do
|
18
20
|
include MongoidHashQuery
|
21
|
+
include Rack::Reqorder::Monitor::Helpers
|
19
22
|
end
|
20
23
|
|
21
24
|
version 'v1', using: :path, vendor: 'foobar'
|
22
25
|
format :json
|
23
26
|
prefix :api
|
24
27
|
|
28
|
+
=begin
|
29
|
+
rescue_from Grape::Exceptions::ValidationErrors do |e|
|
30
|
+
error!({errors: e.send(:full_messages)}, 422)
|
31
|
+
end
|
32
|
+
=end
|
33
|
+
|
25
34
|
#collection routes
|
26
35
|
resource :route_paths do
|
36
|
+
before do
|
37
|
+
authorize_user!(headers) unless Rack::Reqorder.configuration.no_auth
|
38
|
+
end
|
39
|
+
|
27
40
|
get do
|
28
41
|
route_paths = apply_filters(RoutePath.all, params)
|
29
42
|
|
@@ -46,8 +59,23 @@ module Rack::Reqorder::Monitor
|
|
46
59
|
end
|
47
60
|
end
|
48
61
|
|
62
|
+
#collection routes
|
63
|
+
resource :route_path_24_statistics do
|
64
|
+
get do
|
65
|
+
route_paths = RoutePath.all
|
66
|
+
|
67
|
+
route_paths = apply_filters(route_paths, params)
|
68
|
+
|
69
|
+
present(route_paths, with: RoutePath24StatisticsEntity)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
49
73
|
#collection routes
|
50
74
|
resource :requests do
|
75
|
+
before do
|
76
|
+
authorize_user!(headers) unless Rack::Reqorder.configuration.no_auth
|
77
|
+
end
|
78
|
+
|
51
79
|
get do
|
52
80
|
requests = apply_filters(HttpRequest.all, params)
|
53
81
|
|
@@ -72,6 +100,10 @@ module Rack::Reqorder::Monitor
|
|
72
100
|
|
73
101
|
#collection routes
|
74
102
|
resource :responses do
|
103
|
+
before do
|
104
|
+
authorize_user!(headers) unless Rack::Reqorder.configuration.no_auth
|
105
|
+
end
|
106
|
+
|
75
107
|
get do
|
76
108
|
responses = HttpResponse.all
|
77
109
|
|
@@ -98,9 +130,15 @@ module Rack::Reqorder::Monitor
|
|
98
130
|
|
99
131
|
#collection routes
|
100
132
|
resource :faults do
|
133
|
+
before do
|
134
|
+
authorize_user!(headers) unless Rack::Reqorder.configuration.no_auth
|
135
|
+
end
|
136
|
+
|
101
137
|
get do
|
102
138
|
faults = AppFault.all
|
103
139
|
|
140
|
+
environments = faults.group_by(&:environment).keys
|
141
|
+
|
104
142
|
faults = apply_filters(faults, params)
|
105
143
|
|
106
144
|
meta_aggregations = aggregations(faults, params)
|
@@ -110,7 +148,7 @@ module Rack::Reqorder::Monitor
|
|
110
148
|
present_with_meta(
|
111
149
|
faults,
|
112
150
|
present(faults, with: FaultEntity),
|
113
|
-
meta_aggregations
|
151
|
+
meta_aggregations.merge(environments: environments)
|
114
152
|
)
|
115
153
|
end
|
116
154
|
|
@@ -119,11 +157,28 @@ module Rack::Reqorder::Monitor
|
|
119
157
|
get do
|
120
158
|
present(AppFault.find(params[:id]), with: FaultEntity)
|
121
159
|
end
|
160
|
+
|
161
|
+
params do
|
162
|
+
requires :fault, type: Hash do
|
163
|
+
optional :resolved, type: Boolean
|
164
|
+
end
|
165
|
+
end
|
166
|
+
put do
|
167
|
+
fault = AppFault.find(params[:id])
|
168
|
+
fault.resolved = declared(params)[:fault][:resolved]
|
169
|
+
fault.save!
|
170
|
+
|
171
|
+
present(fault, with: FaultEntity)
|
172
|
+
end
|
122
173
|
end
|
123
174
|
end
|
124
175
|
|
125
176
|
#collection routes
|
126
177
|
resource :exceptions do
|
178
|
+
before do
|
179
|
+
authorize_user!(headers) unless Rack::Reqorder.configuration.no_auth
|
180
|
+
end
|
181
|
+
|
127
182
|
get do
|
128
183
|
exceptions = AppException.all
|
129
184
|
|
@@ -148,24 +203,39 @@ module Rack::Reqorder::Monitor
|
|
148
203
|
end
|
149
204
|
end
|
150
205
|
|
206
|
+
|
207
|
+
params do
|
208
|
+
requires :user, type: Hash do
|
209
|
+
requires :email, type: String
|
210
|
+
requires :password, type: String
|
211
|
+
end
|
212
|
+
end
|
213
|
+
resource :sessions do
|
214
|
+
post do
|
215
|
+
authenticate_user!(declared(params))
|
216
|
+
|
217
|
+
present(Object.new, with: SessionEntity)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
151
221
|
helpers do
|
152
222
|
def present_with_meta(object, hash, extra_meta)
|
153
223
|
hash[:meta] = {
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
224
|
+
current_page: object.current_page,
|
225
|
+
next_page: object.next_page,
|
226
|
+
prev_page: object.prev_page,
|
227
|
+
total_pages: object.total_pages,
|
228
|
+
total_count: object.total_count
|
159
229
|
}.merge(extra_meta)
|
160
230
|
|
161
231
|
return hash
|
162
232
|
end
|
163
233
|
|
164
234
|
def paginate(object, params)
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
235
|
+
object = object.page(params[:page] || 1).per(params[:per_page] || 30)
|
236
|
+
object = object.skip(params[:skip]) if params[:skip]
|
237
|
+
|
238
|
+
return object
|
169
239
|
end
|
170
240
|
end
|
171
241
|
|
@@ -38,9 +38,11 @@ module Rack::Reqorder::Monitor
|
|
38
38
|
expose :http_method
|
39
39
|
expose :statistic_all, using: StatisticEntity
|
40
40
|
|
41
|
+
=begin
|
41
42
|
1.upto(24) do |num|
|
42
43
|
expose "statistic_#{num}", using: StatisticEntity
|
43
44
|
end
|
45
|
+
=end
|
44
46
|
|
45
47
|
with_options(format_with: :iso_timestamp) do
|
46
48
|
expose :created_at
|
@@ -48,6 +50,55 @@ module Rack::Reqorder::Monitor
|
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
53
|
+
class RoutePath24StatisticsEntity < Grape::Entity
|
54
|
+
root :route_path_25_statistics
|
55
|
+
present_collection true
|
56
|
+
|
57
|
+
exposures = proc{|aggrs, field|
|
58
|
+
aggrs.each do |aggr|
|
59
|
+
expose aggr do |route_path, options|
|
60
|
+
today_array = []
|
61
|
+
yesterday_array = []
|
62
|
+
|
63
|
+
now = DateTime.now.utc.hour
|
64
|
+
|
65
|
+
0.upto(now) do |i|
|
66
|
+
today_array.push(
|
67
|
+
route_path[:items].where(
|
68
|
+
"statistic_#{i}.created_at".to_sym.gte => DateTime.now.utc.to_date
|
69
|
+
).send(aggr,("statistic_#{i}.#{field}"))
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
if now <23
|
74
|
+
(now+1).upto(23) do |i|
|
75
|
+
yesterday_array.push(
|
76
|
+
route_path[:items].where(
|
77
|
+
"statistic_#{i}.created_at".to_sym.gte => (DateTime.now.utc.to_date - 1)
|
78
|
+
).send(aggr,("statistic_#{i}.#{field}"))
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
[yesterday_array,today_array].flatten
|
84
|
+
end
|
85
|
+
end
|
86
|
+
}
|
87
|
+
|
88
|
+
[:http_requests_count, :statuses_2xx, :statuses_3xx, :statuses_4xx,
|
89
|
+
:statuses_401, :statuses_404, :statuses_422, :statuses_5xx,
|
90
|
+
:xhr_count, :ssl_count
|
91
|
+
].each do |field|
|
92
|
+
expose field do
|
93
|
+
exposures.call([:sum], field)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
expose :avg_response_time do
|
98
|
+
exposures.call([:avg], :avg_response_time)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
51
102
|
class RequestEntity < BaseEntity
|
52
103
|
root :requests, :request
|
53
104
|
|
@@ -100,15 +151,21 @@ module Rack::Reqorder::Monitor
|
|
100
151
|
expose :e_class
|
101
152
|
expose :line
|
102
153
|
expose :filepath
|
154
|
+
expose :resolved
|
103
155
|
expose :app_exceptions_count, as: :exceptions_count
|
156
|
+
expose :environment
|
104
157
|
expose :message do |fault, options|
|
105
|
-
fault.app_exceptions.try(:
|
158
|
+
fault.app_exceptions.try(:last).try(:message)
|
106
159
|
end
|
107
160
|
|
108
161
|
expose :app_exception_ids, as: :exception_ids do |fault, options|
|
109
162
|
fault.app_exception_ids.map(&:to_s).first(100)
|
110
163
|
end
|
111
164
|
|
165
|
+
with_options(format_with: :association_id) do
|
166
|
+
expose :route_path, as: :route_path_id
|
167
|
+
end
|
168
|
+
|
112
169
|
with_options(format_with: :iso_timestamp) do
|
113
170
|
expose :created_at
|
114
171
|
expose :updated_at
|
@@ -136,5 +193,23 @@ module Rack::Reqorder::Monitor
|
|
136
193
|
end
|
137
194
|
|
138
195
|
end
|
196
|
+
|
197
|
+
class SessionEntity < Grape::Entity
|
198
|
+
expose :id do |status, options|
|
199
|
+
1
|
200
|
+
end
|
201
|
+
|
202
|
+
expose :email do |status, options|
|
203
|
+
Rack::Reqorder.configuration.auth_email
|
204
|
+
end
|
205
|
+
|
206
|
+
expose :token do |status, options|
|
207
|
+
#need user object...
|
208
|
+
Digest::MD5.hexdigest(
|
209
|
+
Rack::Reqorder.configuration.auth_email +
|
210
|
+
Rack::Reqorder.configuration.auth_password
|
211
|
+
)
|
212
|
+
end
|
213
|
+
end
|
139
214
|
end
|
140
215
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Rack::Reqorder::Monitor
|
2
|
+
module Helpers
|
3
|
+
def authorize_user!(headers)
|
4
|
+
authorize_user(headers) ? true : error!('403 Forbidden', 403)
|
5
|
+
end
|
6
|
+
|
7
|
+
def authenticate_user!(params)
|
8
|
+
authenticate_user(params) ? true : error!('401 Unauthorized', 401)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
#monkeypatch these 2 methods if you want to provide custom authentication/authorization
|
13
|
+
def authorize_user(headers)
|
14
|
+
token, options = AuthorizationHeader.token_and_options(headers)
|
15
|
+
|
16
|
+
user_email = options.blank?? nil : options[:email]
|
17
|
+
|
18
|
+
correct_email = user_email == Rack::Reqorder.configuration.auth_email
|
19
|
+
correct_token = token == user_email_password_md5
|
20
|
+
|
21
|
+
return (correct_email && correct_token) ? true : false
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def authenticate_user(params)
|
26
|
+
email = params.user.email
|
27
|
+
password = params.user.password
|
28
|
+
|
29
|
+
correct_email = email == Rack::Reqorder.configuration.auth_email
|
30
|
+
correct_password = password == Rack::Reqorder.configuration.auth_password
|
31
|
+
|
32
|
+
return (correct_email && correct_password)? true : false
|
33
|
+
end
|
34
|
+
|
35
|
+
def user_email_password_md5(user: nil)
|
36
|
+
#if user.nil?
|
37
|
+
Digest::MD5.hexdigest(
|
38
|
+
Rack::Reqorder.configuration.auth_email +
|
39
|
+
Rack::Reqorder.configuration.auth_password
|
40
|
+
)
|
41
|
+
#else
|
42
|
+
#end
|
43
|
+
end
|
44
|
+
#taken from rails ActionController::HttpAuthentication::Token ^_^
|
45
|
+
class AuthorizationHeader
|
46
|
+
class << self
|
47
|
+
TOKEN_KEY = 'token='
|
48
|
+
TOKEN_REGEX = /^(Token|Bearer) /
|
49
|
+
AUTHN_PAIR_DELIMITERS = /(?:,|;|\t+)/
|
50
|
+
|
51
|
+
def token_and_options(headers)
|
52
|
+
authorization_request = headers['Authorization']
|
53
|
+
|
54
|
+
if authorization_request[TOKEN_REGEX]
|
55
|
+
params = token_params_from authorization_request
|
56
|
+
[params.shift[1], Hash[params].with_indifferent_access]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def token_params_from(auth)
|
63
|
+
rewrite_param_values params_array_from raw_params auth
|
64
|
+
end
|
65
|
+
|
66
|
+
# Takes raw_params and turns it into an array of parameters
|
67
|
+
def params_array_from(raw_params)
|
68
|
+
raw_params.map { |param| param.split %r/=(.+)?/ }
|
69
|
+
end
|
70
|
+
|
71
|
+
# This removes the <tt>"</tt> characters wrapping the value.
|
72
|
+
def rewrite_param_values(array_params)
|
73
|
+
array_params.each { |param| (param[1] || "").gsub! %r/^"|"$/, '' }
|
74
|
+
end
|
75
|
+
|
76
|
+
# This method takes an authorization body and splits up the key-value
|
77
|
+
# pairs by the standardized <tt>:</tt>, <tt>;</tt>, or <tt>\t</tt>
|
78
|
+
# delimiters defined in +AUTHN_PAIR_DELIMITERS+.
|
79
|
+
def raw_params(auth)
|
80
|
+
_raw_params = auth.sub(TOKEN_REGEX, '').split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
|
81
|
+
|
82
|
+
if !(_raw_params.first =~ %r{\A#{TOKEN_KEY}})
|
83
|
+
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
|
84
|
+
end
|
85
|
+
|
86
|
+
_raw_params
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Rack
|
2
|
+
module Reqorder
|
3
|
+
module RailsRecognizer
|
4
|
+
def prefixes
|
5
|
+
return @prefixes unless @prefixes.blank?
|
6
|
+
|
7
|
+
@prefixes = {} #{'/mount_prefix' => {search_method: xxx_recognize_path, rack_app: xxx}}
|
8
|
+
Rails.application.routes.routes.routes.select{|r| r.defaults.blank?}.each do |route|
|
9
|
+
__superclass = route.app.try(:superclass) || route.app.try(:app).try(:superclass)
|
10
|
+
|
11
|
+
next unless __superclass
|
12
|
+
|
13
|
+
case __superclass.to_s
|
14
|
+
when Sinatra::Base.to_s
|
15
|
+
@prefixes[route.path.spec.try(:left).to_s + route.path.spec.try(:right).to_s] = {
|
16
|
+
search_method: :sinatra_recognize_path,
|
17
|
+
rack_app: route.app.try(:superclass).nil? ? route.app.app : route.app
|
18
|
+
}
|
19
|
+
when Rails::Engine.to_s
|
20
|
+
@prefixes[route.path.spec.try(:left).to_s + route.path.spec.try(:right).to_s] = {
|
21
|
+
search_method: :rails_recognize_path,
|
22
|
+
rack_app: route.app.try(:superclass).nil? ? route.app.app : route.app
|
23
|
+
}
|
24
|
+
when Grape::API.to_s
|
25
|
+
@prefixes[route.path.spec.try(:left).to_s + route.path.spec.try(:right).to_s] = {
|
26
|
+
search_method: :grape_recognize_path,
|
27
|
+
rack_app: route.app.try(:superclass).nil? ? route.app.app : route.app
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
return @prefixes
|
33
|
+
end
|
34
|
+
|
35
|
+
def rails_paths(rails_app)
|
36
|
+
paths = {}
|
37
|
+
rails_app.routes.routes.routes.reverse.each do |route|
|
38
|
+
paths[route.defaults] = route.path.spec.to_s.gsub('(.:format)', '')
|
39
|
+
end
|
40
|
+
|
41
|
+
return paths
|
42
|
+
end
|
43
|
+
|
44
|
+
def recognize_unknown_path
|
45
|
+
prefixes.each do |prefix, engine|
|
46
|
+
if path_uri.start_with?(prefix)
|
47
|
+
return prefix
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
return ''
|
52
|
+
end
|
53
|
+
|
54
|
+
def recognize_path(path_uri, options = {})
|
55
|
+
prefixes.each do |prefix, engine|
|
56
|
+
if path_uri.start_with?(prefix)
|
57
|
+
return prefix + self.send(engine[:search_method].to_sym, {
|
58
|
+
path_uri: path_uri.gsub(prefix, ''),
|
59
|
+
rack_app: engine[:rack_app],
|
60
|
+
options: options
|
61
|
+
})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
begin
|
66
|
+
return rails_recognize_path(
|
67
|
+
path_uri: path_uri,
|
68
|
+
rack_app: Rails.application,
|
69
|
+
options: options
|
70
|
+
)
|
71
|
+
rescue ActionController::RoutingError
|
72
|
+
return "/#{path_uri.split('/')[1]}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#rack_app is basically a rails app here but we keep it for the sake of the interface
|
77
|
+
def rails_recognize_path(path_uri:, rack_app:, options: {})
|
78
|
+
memoized_var = "@#{rack_app.class.to_s.split('::').join('_').downcase}".to_sym
|
79
|
+
|
80
|
+
if self.instance_variable_get(memoized_var).nil?
|
81
|
+
self.instance_variable_set(memoized_var, rails_paths(rack_app))
|
82
|
+
end
|
83
|
+
|
84
|
+
Rack::Reqorder.instance_variable_get(memoized_var)[
|
85
|
+
rack_app.routes.recognize_path(path_uri, options)
|
86
|
+
.select{|key, value| [:action, :controller].include?(key)}
|
87
|
+
]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module GrapeRecognizer
|
92
|
+
def recognize_path(path_uri, options = {})
|
93
|
+
raise 'not implemented yet'
|
94
|
+
end
|
95
|
+
|
96
|
+
def grape_recognize_path(path_uri:, rack_app:, options: {})
|
97
|
+
path_uri = '/' if path_uri.blank?
|
98
|
+
|
99
|
+
rack_app.routes.each do |route|
|
100
|
+
route_options = route.instance_variable_get(:@options)
|
101
|
+
if route_options[:method] == options[:method] && route_options[:compiled] =~ path_uri
|
102
|
+
if route_options[:method] == "OPTIONS"
|
103
|
+
return route_options[:path].
|
104
|
+
gsub('(.json)', '')
|
105
|
+
else
|
106
|
+
return route_options[:path].
|
107
|
+
gsub(':version', route_options[:version]).
|
108
|
+
gsub('(.json)', '')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#assets in grape? well you never know..
|
114
|
+
if path_uri.end_with?('.js')
|
115
|
+
return '/js_asset'
|
116
|
+
elsif path_uri.end_with?('.css')
|
117
|
+
return '/css_asset'
|
118
|
+
elsif path_uri.end_with?('.png', 'jpg')
|
119
|
+
return '/css_asset'
|
120
|
+
else
|
121
|
+
return '/unknown' #path_uri
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
module SinatraRecognizer
|
127
|
+
def recognize_path(path_uri, options = {})
|
128
|
+
raise 'not implemented yet'
|
129
|
+
end
|
130
|
+
|
131
|
+
def sinatra_recognize_path(path_uri:, rack_app:, options: {})
|
132
|
+
path_uri = '/' if path_uri.blank?
|
133
|
+
|
134
|
+
rack_app.routes[options[:method].to_s.upcase].each do |r|
|
135
|
+
if r.first =~ path_uri
|
136
|
+
return r.first.to_s.
|
137
|
+
gsub('([^\\/?#]+)', ":#{r[1].first}").
|
138
|
+
gsub('\\z)','').gsub('(?-mix:\\A', '').
|
139
|
+
gsub('\\','')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
if path_uri.end_with?('.js')
|
144
|
+
return '/js_asset'
|
145
|
+
elsif path_uri.end_with?('.css')
|
146
|
+
return '/css_asset'
|
147
|
+
elsif path_uri.end_with?('.png', 'jpg')
|
148
|
+
return '/css_asset'
|
149
|
+
else
|
150
|
+
return '/unknown' #path_uri
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
@@ -0,0 +1,29 @@
|
|
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
|
data/rack-reqorder.gemspec
CHANGED
@@ -6,12 +6,12 @@ require 'rack/reqorder/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "rack-reqorder"
|
8
8
|
spec.version = Rack::Reqorder::VERSION
|
9
|
-
spec.authors = ["Filippos Vasilakis"]
|
10
|
-
spec.email = ["vasilakisfil@gmail.com"]
|
9
|
+
spec.authors = ["Filippos Vasilakis", "Kollegorna"]
|
10
|
+
spec.email = ["vasilakisfil@gmail.com", "admin@kollegorna.se"]
|
11
11
|
|
12
12
|
spec.summary = %q{Request recorder and analyzer for rack apps}
|
13
13
|
spec.description = %q{Request recorder and analyzer for rack apps}
|
14
|
-
spec.homepage = ""
|
14
|
+
spec.homepage = "https://github.com/kollegorna/rack-reqorder"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -20,8 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.8"
|
22
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "pry"
|
24
|
+
spec.add_development_dependency "factory_girl", "~> 4.0"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "faker"
|
23
27
|
spec.add_dependency "mongoid", "~> 4.0.0"
|
24
|
-
spec.add_dependency "activesupport", "
|
28
|
+
spec.add_dependency "activesupport", ">4.0.0"
|
25
29
|
spec.add_dependency "grape"
|
26
30
|
spec.add_dependency "grape-entity"
|
27
31
|
spec.add_dependency "kaminari"
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-reqorder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Filippos Vasilakis
|
8
|
+
- Kollegorna
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2015-
|
12
|
+
date: 2015-10-12 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
@@ -38,6 +39,62 @@ dependencies:
|
|
38
39
|
- - "~>"
|
39
40
|
- !ruby/object:Gem::Version
|
40
41
|
version: '10.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: pry
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: factory_girl
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '4.0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '4.0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: faker
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
41
98
|
- !ruby/object:Gem::Dependency
|
42
99
|
name: mongoid
|
43
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,16 +113,16 @@ dependencies:
|
|
56
113
|
name: activesupport
|
57
114
|
requirement: !ruby/object:Gem::Requirement
|
58
115
|
requirements:
|
59
|
-
- - "
|
116
|
+
- - ">"
|
60
117
|
- !ruby/object:Gem::Version
|
61
|
-
version: 4.
|
118
|
+
version: 4.0.0
|
62
119
|
type: :runtime
|
63
120
|
prerelease: false
|
64
121
|
version_requirements: !ruby/object:Gem::Requirement
|
65
122
|
requirements:
|
66
|
-
- - "
|
123
|
+
- - ">"
|
67
124
|
- !ruby/object:Gem::Version
|
68
|
-
version: 4.
|
125
|
+
version: 4.0.0
|
69
126
|
- !ruby/object:Gem::Dependency
|
70
127
|
name: grape
|
71
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,6 +196,7 @@ dependencies:
|
|
139
196
|
description: Request recorder and analyzer for rack apps
|
140
197
|
email:
|
141
198
|
- vasilakisfil@gmail.com
|
199
|
+
- admin@kollegorna.se
|
142
200
|
executables: []
|
143
201
|
extensions: []
|
144
202
|
extra_rdoc_files: []
|
@@ -164,11 +222,14 @@ files:
|
|
164
222
|
- lib/rack/reqorder/models/statistic.rb
|
165
223
|
- lib/rack/reqorder/monitor.rb
|
166
224
|
- lib/rack/reqorder/monitor/entities.rb
|
225
|
+
- lib/rack/reqorder/monitor/helpers.rb
|
226
|
+
- lib/rack/reqorder/route_recognizers.rb
|
167
227
|
- lib/rack/reqorder/services/backtrace_cleaner.rb
|
168
228
|
- lib/rack/reqorder/tasks/routes.rake
|
229
|
+
- lib/rack/reqorder/tasks/test_database.rake
|
169
230
|
- lib/rack/reqorder/version.rb
|
170
231
|
- rack-reqorder.gemspec
|
171
|
-
homepage:
|
232
|
+
homepage: https://github.com/kollegorna/rack-reqorder
|
172
233
|
licenses:
|
173
234
|
- MIT
|
174
235
|
metadata: {}
|
@@ -188,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
249
|
version: '0'
|
189
250
|
requirements: []
|
190
251
|
rubyforge_project:
|
191
|
-
rubygems_version: 2.4.
|
252
|
+
rubygems_version: 2.4.8
|
192
253
|
signing_key:
|
193
254
|
specification_version: 4
|
194
255
|
summary: Request recorder and analyzer for rack apps
|