meta_request 0.6.0 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 184437fd6ea42cfd3276c87c21442aa47263b87f
4
- data.tar.gz: 599aece8423f131b32b7da83c0e2ec7253abfe9a
2
+ SHA256:
3
+ metadata.gz: c006823c94849fdbbd3a58e7c8f28383f29a184da0d5a0ec18ae21d7a309479b
4
+ data.tar.gz: 3530b801762849da7835dddea6b89861fb98402a0aa1507c8c558f7be3da5faa
5
5
  SHA512:
6
- metadata.gz: eb35b8df716f3f84501d05e3dc51e831ac0bf915a07521236a9938baeb0be9d99499da9ff9d2e8382e6f60c2ecf7aca872d43d1f3f4e580188330ceb717daaff
7
- data.tar.gz: 2ffdf7da526cfa5a1be4a68c52affbaea939961be31afbcf4725840dac7b645fb84b59ace8b0e6ad0829b95036ad3a89135ee60c4e1b873d829f76e737880310
6
+ metadata.gz: a0a20933e32b050f3e42c035dadc40080479100fe1e7951ea828e2d958f17b00b6cae434afcea39fab268d68e7cb51b058aa2ef08c536eb477f932f591a1b9fd
7
+ data.tar.gz: d06f1f7b2d846297ec8f3475d75cc19ffa0f76f5ef333428d9713ef43f84e4cb15ecabbd638f36bd55ac65c9f2bce46dd80054b81fb906262b377804e7021932
data/README.md CHANGED
@@ -1,55 +1,79 @@
1
- # MetaRequest
2
-
3
- Supporting gem for [Rails Panel (Google Chrome extension for Rails development)](https://github.com/dejan/rails_panel).
4
-
5
- ## Installation
6
-
7
- Add meta_request gem to development group in Gemfile:
8
-
9
- ```ruby
10
- group :development do
11
- gem 'meta_request'
12
- end
13
- ```
14
-
15
- ## Usage
16
-
17
- See [Rails Panel extension](https://github.com/dejan/rails_panel).
18
-
19
- ## Compatibility Warnings
20
-
21
- If you're using [LiveReload](http://livereload.com/) or
22
- [Rack::LiveReload](https://github.com/johnbintz/rack-livereload) make sure to
23
- exclude watching your tmp/ folder because meta_request writes a lot of data there
24
- and your browser will refresh like a madman.
25
-
26
- ## Development
27
-
28
- Run tests:
29
-
30
- make
31
-
32
- ## Licence
33
-
34
- Copyright (c) 2012 Dejan Simic
35
-
36
- MIT License
37
-
38
- Permission is hereby granted, free of charge, to any person obtaining
39
- a copy of this software and associated documentation files (the
40
- "Software"), to deal in the Software without restriction, including
41
- without limitation the rights to use, copy, modify, merge, publish,
42
- distribute, sublicense, and/or sell copies of the Software, and to
43
- permit persons to whom the Software is furnished to do so, subject to
44
- the following conditions:
45
-
46
- The above copyright notice and this permission notice shall be
47
- included in all copies or substantial portions of the Software.
48
-
49
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
52
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
53
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
54
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
55
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ # MetaRequest
2
+
3
+ Supporting gem for [Rails Panel (Google Chrome extension for Rails development)](https://github.com/dejan/rails_panel).
4
+
5
+ ## Installation
6
+
7
+ Add meta_request gem to development group in Gemfile:
8
+
9
+ ```ruby
10
+ group :development do
11
+ gem 'meta_request'
12
+ end
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ See [Rails Panel extension](https://github.com/dejan/rails_panel).
18
+
19
+ ## Compatibility Warnings
20
+
21
+ If you're using [LiveReload](http://livereload.com/) or
22
+ [Rack::LiveReload](https://github.com/johnbintz/rack-livereload) make sure to
23
+ exclude watching your tmp/ folder because meta_request writes a lot of data there
24
+ and your browser will refresh like a madman.
25
+
26
+ ## Configuration
27
+
28
+ Gem can be configured using block:
29
+
30
+ ```ruby
31
+ MetaRequest.configure do |config|
32
+ config.storage_pool_size = 30
33
+ end
34
+ ```
35
+
36
+ List of available attributes and defaults can be found in [lib/meta_request/config.rb](lib/meta_request/config.rb).
37
+
38
+ ## Docker
39
+
40
+ Apps runing in Docker container will have filepaths of the container so links to editor would not work. To fix this, you need to propagate working directory through enviroment variable `SOURCE_PATH`. With docker-compose it can be done like this:
41
+
42
+ ```yaml
43
+ services:
44
+ app:
45
+ environment:
46
+ - SOURCE_PATH=$PWD
47
+ # ...
48
+ ```
49
+
50
+ ## Development
51
+
52
+ Run all tests:
53
+
54
+ docker-compose up
55
+
56
+ ## Licence
57
+
58
+ Copyright (c) 2012 Dejan Simic
59
+
60
+ MIT License
61
+
62
+ Permission is hereby granted, free of charge, to any person obtaining
63
+ a copy of this software and associated documentation files (the
64
+ "Software"), to deal in the Software without restriction, including
65
+ without limitation the rights to use, copy, modify, merge, publish,
66
+ distribute, sublicense, and/or sell copies of the Software, and to
67
+ permit persons to whom the Software is furnished to do so, subject to
68
+ the following conditions:
69
+
70
+ The above copyright notice and this permission notice shall be
71
+ included in all copies or substantial portions of the Software.
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
74
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
75
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
76
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
77
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
78
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
79
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,86 +1,88 @@
1
- module MetaRequest
2
- class AppNotifications
3
-
4
- # these are the specific keys in the cache payload that we display in the
5
- # panel view
6
- CACHE_KEY_COLUMNS = [:key, :hit, :options, :type]
7
-
8
- # define this here so we can pass it in to all of our cache subscribe calls
9
- CACHE_BLOCK = Proc.new {|*args|
10
- name, start, ending, transaction_id, payload = args
11
-
12
- # from http://edgeguides.rubyonrails.org/active_support_instrumentation.html#cache-fetch-hit-active-support
13
- #
14
- # :super_operation :fetch is added when a read is used with #fetch
15
- #
16
- # so if :super_operation is present, we'll use it for the type. otherwise
17
- # strip (say) 'cache_delete.active_support' down to 'delete'
18
- payload[:type] = payload.delete(:super_operation) || name.sub(/cache_(.*?)\..*$/, '\1')
19
-
20
- # anything that isn't in CACHE_KEY_COLUMNS gets shoved into :options
21
- # instead
22
- payload[:options] = {}
23
- payload.keys.each do |k|
24
- payload[:options][k] = payload.delete(k) unless k.in? CACHE_KEY_COLUMNS
25
- end
26
-
27
- dev_caller = caller.detect { |c| c.include? MetaRequest.rails_root }
28
- if dev_caller
29
- c = Callsite.parse(dev_caller)
30
- payload.merge!(:line => c.line, :filename => c.filename, :method => c.method)
31
- end
32
-
33
- Event.new(name, start, ending, transaction_id, payload)
34
- }
35
-
36
- # sql processing block - used for sql.active_record and sql.sequel
37
-
38
- # HACK: we hardcode the event name to 'sql.active_record' so that the ui will
39
- # display sequel events without modification. otherwise the ui would need to
40
- # be modified to support a sequel tab (or to change the display name on the
41
- # active_record tab when necessary - which maybe makes more sense?)
42
- SQL_EVENT_NAME = "sql.active_record"
43
-
44
- SQL_BLOCK = Proc.new {|*args|
45
- name, start, ending, transaction_id, payload = args
46
- dev_caller = caller.detect { |c| c.include? MetaRequest.rails_root }
47
- if dev_caller
48
- c = Callsite.parse(dev_caller)
49
- payload.merge!(:line => c.line, :filename => c.filename, :method => c.method)
50
- end
51
- Event.new(SQL_EVENT_NAME, start, ending, transaction_id, payload)
52
- }
53
- # Subscribe to all events relevant to RailsPanel
54
- #
55
- def self.subscribe
56
- new.
57
- subscribe("meta_request.log").
58
- subscribe("sql.active_record", &SQL_BLOCK).
59
- subscribe("sql.sequel", &SQL_BLOCK).
60
- subscribe("render_partial.action_view").
61
- subscribe("render_template.action_view").
62
- subscribe("process_action.action_controller.exception").
63
- subscribe("process_action.action_controller") do |*args|
64
- name, start, ending, transaction_id, payload = args
65
- payload[:status] = '500' if payload[:exception]
66
- Event.new(name, start, ending, transaction_id, payload)
67
- end.
68
- subscribe("cache_read.active_support", &CACHE_BLOCK).
69
- subscribe("cache_generate.active_support", &CACHE_BLOCK).
70
- subscribe("cache_fetch_hit.active_support", &CACHE_BLOCK).
71
- subscribe("cache_write.active_support", &CACHE_BLOCK).
72
- subscribe("cache_delete.active_support", &CACHE_BLOCK).
73
- subscribe("cache_exist?.active_support", &CACHE_BLOCK)
74
- end
75
-
76
- def subscribe(event_name)
77
- ActiveSupport::Notifications.subscribe(event_name) do |*args|
78
- event = block_given?? yield(*args) : Event.new(*args)
79
- AppRequest.current.events << event if AppRequest.current
80
- end
81
- self
82
- end
83
-
84
- end
85
-
86
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ class AppNotifications
5
+ # these are the specific keys in the cache payload that we display in the
6
+ # panel view
7
+ CACHE_KEY_COLUMNS = %i[key hit options type].freeze
8
+
9
+ # define this here so we can pass it in to all of our cache subscribe calls
10
+ CACHE_BLOCK = proc { |*args|
11
+ name, start, ending, transaction_id, payload = args
12
+
13
+ # from http://edgeguides.rubyonrails.org/active_support_instrumentation.html#cache-fetch-hit-active-support
14
+ #
15
+ # :super_operation :fetch is added when a read is used with #fetch
16
+ #
17
+ # so if :super_operation is present, we'll use it for the type. otherwise
18
+ # strip (say) 'cache_delete.active_support' down to 'delete'
19
+ payload[:type] = payload.delete(:super_operation) || name.sub(/cache_(.*?)\..*$/, '\1')
20
+
21
+ # anything that isn't in CACHE_KEY_COLUMNS gets shoved into :options
22
+ # instead
23
+ payload[:options] = {}
24
+ payload.keys.each do |k|
25
+ payload[:options][k] = payload.delete(k) unless k.in? CACHE_KEY_COLUMNS
26
+ end
27
+
28
+ callsite = Utils.dev_callsite(caller)
29
+ payload.merge!(callsite) if callsite
30
+
31
+ Event.new(name, start, ending, transaction_id, payload)
32
+ }
33
+
34
+ # sql processing block - used for sql.active_record and sql.sequel
35
+
36
+ # HACK: we hardcode the event name to 'sql.active_record' so that the ui will
37
+ # display sequel events without modification. otherwise the ui would need to
38
+ # be modified to support a sequel tab (or to change the display name on the
39
+ # active_record tab when necessary - which maybe makes more sense?)
40
+ SQL_EVENT_NAME = 'sql.active_record'
41
+
42
+ SQL_BLOCK = proc { |*args|
43
+ _name, start, ending, transaction_id, payload = args
44
+ callsite = Utils.dev_callsite(caller)
45
+ payload.merge!(callsite) if callsite
46
+
47
+ Event.new(SQL_EVENT_NAME, start, ending, transaction_id, payload)
48
+ }
49
+
50
+ VIEW_BLOCK = proc { |*args|
51
+ name, start, ending, transaction_id, payload = args
52
+ payload[:identifier] = MetaRequest::Utils.sub_source_path(payload[:identifier])
53
+
54
+ Event.new(name, start, ending, transaction_id, payload)
55
+ }
56
+
57
+ # Subscribe to all events relevant to RailsPanel
58
+ #
59
+ def self.subscribe
60
+ new
61
+ .subscribe('meta_request.log')
62
+ .subscribe('sql.active_record', &SQL_BLOCK)
63
+ .subscribe('sql.sequel', &SQL_BLOCK)
64
+ .subscribe('render_partial.action_view', &VIEW_BLOCK)
65
+ .subscribe('render_template.action_view', &VIEW_BLOCK)
66
+ .subscribe('process_action.action_controller.exception')
67
+ .subscribe('process_action.action_controller') do |*args|
68
+ name, start, ending, transaction_id, payload = args
69
+ payload[:status] = '500' if payload[:exception]
70
+ Event.new(name, start, ending, transaction_id, payload)
71
+ end
72
+ .subscribe('cache_read.active_support', &CACHE_BLOCK)
73
+ .subscribe('cache_generate.active_support', &CACHE_BLOCK)
74
+ .subscribe('cache_fetch_hit.active_support', &CACHE_BLOCK)
75
+ .subscribe('cache_write.active_support', &CACHE_BLOCK)
76
+ .subscribe('cache_delete.active_support', &CACHE_BLOCK)
77
+ .subscribe('cache_exist?.active_support', &CACHE_BLOCK)
78
+ end
79
+
80
+ def subscribe(event_name)
81
+ ActiveSupport::Notifications.subscribe(event_name) do |*args|
82
+ event = block_given? ? yield(*args) : Event.new(*args)
83
+ AppRequest.current.events << event if AppRequest.current
84
+ end
85
+ self
86
+ end
87
+ end
88
+ end
@@ -1,19 +1,20 @@
1
- module MetaRequest
2
- class AppRequest
3
- attr_reader :id, :events
4
-
5
- def initialize(id)
6
- @id = id
7
- @events = []
8
- end
9
-
10
- def self.current
11
- Thread.current[:meta_request_id]
12
- end
13
-
14
- def current!
15
- Thread.current[:meta_request_id] = self
16
- end
17
-
18
- end
19
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ class AppRequest
5
+ attr_reader :id, :events
6
+
7
+ def initialize(id)
8
+ @id = id
9
+ @events = []
10
+ end
11
+
12
+ def self.current
13
+ Thread.current[:meta_request_id]
14
+ end
15
+
16
+ def current!
17
+ Thread.current[:meta_request_id] = self
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ class Config
5
+ attr_writer :logger, :storage_pool_size, :source_path
6
+
7
+ # logger used for reporting gem's fatal errors
8
+ def logger
9
+ @logger ||= Logger.new(File.join(Rails.root, 'log', 'meta_request.log'))
10
+ end
11
+
12
+ # Number of files kept in storage.
13
+ # Increase when using an application loading many simultaneous requests.
14
+ def storage_pool_size
15
+ @storage_pool_size ||= 20
16
+ end
17
+
18
+ def source_path
19
+ @source_path ||= ENV['SOURCE_PATH'] || Rails.root.to_s
20
+ end
21
+ end
22
+ end
@@ -1,68 +1,78 @@
1
- require 'active_support'
2
- require 'active_support/json'
3
- require 'active_support/core_ext'
4
-
5
- module MetaRequest
6
-
7
- # Subclass of ActiveSupport Event that is JSON encodable
8
- #
9
- class Event < ActiveSupport::Notifications::Event
10
- attr_reader :duration
11
-
12
- def initialize(name, start, ending, transaction_id, payload)
13
- super(name, start, ending, transaction_id, json_encodable(payload))
14
- @duration = 1000.0 * (ending - start)
15
- end
16
-
17
- def self.events_for_exception(exception_wrapper)
18
- if defined?(ActionDispatch::ExceptionWrapper)
19
- exception = exception_wrapper.exception
20
- trace = exception_wrapper.application_trace
21
- trace = exception_wrapper.framework_trace if trace.empty?
22
- else
23
- exception = exception_wrapper
24
- trace = exception.backtrace
25
- end
26
- trace.unshift "#{exception.class} (#{exception.message})"
27
- trace.map do |call|
28
- Event.new('process_action.action_controller.exception', 0, 0, nil, {:call => call})
29
- end
30
- end
31
-
32
- private
33
-
34
- def json_encodable(payload)
35
- return {} unless payload.is_a?(Hash)
36
- transform_hash(payload, :deep => true) { |hash, key, value|
37
- if value.class.to_s == 'ActionDispatch::Http::Headers'
38
- value = value.to_h.select { |k, _| k.upcase == k }
39
- end
40
-
41
- begin
42
- value.to_json(:methods => [:duration])
43
- new_value = value
44
- rescue
45
- new_value = 'Not JSON Encodable'
46
- end
47
- hash[key] = new_value
48
- }.with_indifferent_access
49
- end
50
-
51
- # https://gist.github.com/dbenhur/1070399
52
- def transform_hash(original, options={}, &block)
53
- options[:safe_descent] ||= {}
54
- new_hash = {}
55
- options[:safe_descent][original.object_id] = new_hash
56
- original.inject(new_hash) { |result, (key,value)|
57
- if (options[:deep] && Hash === value)
58
- value = options[:safe_descent].fetch( value.object_id ) {
59
- transform_hash(value, options, &block)
60
- }
61
- end
62
- block.call(result,key,value)
63
- result
64
- }
65
- end
66
-
67
- end
68
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_support/json'
5
+ require 'active_support/core_ext'
6
+
7
+ module MetaRequest
8
+ # Subclass of ActiveSupport Event that is JSON encodable
9
+ #
10
+ class Event < ActiveSupport::Notifications::Event
11
+ NOT_JSON_ENCODABLE = 'Not JSON Encodable'
12
+
13
+ attr_reader :duration
14
+
15
+ def initialize(name, start, ending, transaction_id, payload)
16
+ super(name, start, ending, transaction_id, json_encodable(payload))
17
+ @duration = 1000.0 * (ending - start)
18
+ end
19
+
20
+ def self.events_for_exception(exception_wrapper)
21
+ if defined?(ActionDispatch::ExceptionWrapper)
22
+ exception = exception_wrapper.exception
23
+ trace = exception_wrapper.application_trace
24
+ trace = exception_wrapper.framework_trace if trace.empty?
25
+ else
26
+ exception = exception_wrapper
27
+ trace = exception.backtrace
28
+ end
29
+ trace.unshift "#{exception.class} (#{exception.message})"
30
+ trace.map do |call|
31
+ Event.new('process_action.action_controller.exception', 0, 0, nil, call: call)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def json_encodable(payload)
38
+ return {} unless payload.is_a?(Hash)
39
+
40
+ transform_hash(payload, deep: true) do |hash, key, value|
41
+ if value.class.to_s == 'ActionDispatch::Http::Headers'
42
+ value = value.to_h.select { |k, _| k.upcase == k }
43
+ elsif not_encodable?(value)
44
+ value = NOT_JSON_ENCODABLE
45
+ end
46
+
47
+ begin
48
+ value.to_json(methods: [:duration])
49
+ new_value = value
50
+ rescue StandardError
51
+ new_value = NOT_JSON_ENCODABLE
52
+ end
53
+ hash[key] = new_value
54
+ end.with_indifferent_access
55
+ end
56
+
57
+ def not_encodable?(value)
58
+ (defined?(ActiveRecord) && value.is_a?(ActiveRecord::ConnectionAdapters::AbstractAdapter)) ||
59
+ (defined?(ActionDispatch) &&
60
+ (value.is_a?(ActionDispatch::Request) || value.is_a?(ActionDispatch::Response)))
61
+ end
62
+
63
+ # https://gist.github.com/dbenhur/1070399
64
+ def transform_hash(original, options = {}, &block)
65
+ options[:safe_descent] ||= {}
66
+ new_hash = {}
67
+ options[:safe_descent][original.object_id] = new_hash
68
+ original.each_with_object(new_hash) do |(key, value), result|
69
+ if options[:deep] && Hash === value
70
+ value = options[:safe_descent].fetch(value.object_id) do
71
+ transform_hash(value, options, &block)
72
+ end
73
+ end
74
+ block.call(result, key, value)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -1,49 +1,47 @@
1
- require 'callsite'
2
-
3
- module MetaRequest
4
- module LogInterceptor
5
-
6
- def debug(message=nil, *args)
7
- push_event(:debug, message)
8
- super
9
- end
10
-
11
- def info(message=nil, *args)
12
- push_event(:info, message)
13
- super
14
- end
15
-
16
- def warn(message=nil, *args)
17
- push_event(:warn, message)
18
- super
19
- end
20
-
21
- def error(message=nil, *args)
22
- push_event(:error, message)
23
- super
24
- end
25
-
26
- def fatal(message=nil, *args)
27
- push_event(:fatal, message)
28
- super
29
- end
30
-
31
- def unknown(message=nil, *args)
32
- push_event(:unknown, message)
33
- super
34
- end
35
-
36
-
37
- private
38
- def push_event(level, message)
39
- dev_log = AppRequest.current && caller[1].include?(MetaRequest.rails_root)
40
- if dev_log
41
- c = Callsite.parse(caller[1])
42
- payload = {:message => message, :level => level, :line => c.line, :filename => c.filename, :method => c.method}
43
- AppRequest.current.events << Event.new('meta_request.log', 0, 0, 0, payload)
44
- end
45
- rescue Exception => e
46
- MetaRequest.logger.fatal(e.message + "\n " + e.backtrace.join("\n "))
47
- end
48
- end
49
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ module LogInterceptor
5
+ def debug(message = nil, *args)
6
+ push_event(:debug, message)
7
+ super
8
+ end
9
+
10
+ def info(message = nil, *args)
11
+ push_event(:info, message)
12
+ super
13
+ end
14
+
15
+ def warn(message = nil, *args)
16
+ push_event(:warn, message)
17
+ super
18
+ end
19
+
20
+ def error(message = nil, *args)
21
+ push_event(:error, message)
22
+ super
23
+ end
24
+
25
+ def fatal(message = nil, *args)
26
+ push_event(:fatal, message)
27
+ super
28
+ end
29
+
30
+ def unknown(message = nil, *args)
31
+ push_event(:unknown, message)
32
+ super
33
+ end
34
+
35
+ private
36
+
37
+ def push_event(level, message)
38
+ callsite = AppRequest.current && Utils.dev_callsite(caller.drop(1))
39
+ if callsite
40
+ payload = callsite.merge(message: message, level: level)
41
+ AppRequest.current.events << Event.new('meta_request.log', 0, 0, 0, payload)
42
+ end
43
+ rescue StandardError => e
44
+ MetaRequest.config.logger.fatal(e.message + "\n " + e.backtrace.join("\n "))
45
+ end
46
+ end
47
+ end
@@ -1,32 +1,33 @@
1
- require 'json'
2
-
3
- module MetaRequest
4
- module Middlewares
5
- class AppRequestHandler
6
- def initialize(app)
7
- @app = app
8
- end
9
-
10
- def call(env)
11
- app_request = AppRequest.new env["action_dispatch.request_id"]
12
- app_request.current!
13
- @app.call(env)
14
- rescue Exception => exception
15
- if defined?(ActionDispatch::ExceptionWrapper)
16
- wrapper = if ActionDispatch::ExceptionWrapper.method_defined? :env
17
- ActionDispatch::ExceptionWrapper.new(env, exception)
18
- else
19
- ActionDispatch::ExceptionWrapper.new(env['action_dispatch.backtrace_cleaner'], exception)
20
- end
21
- app_request.events.push(*Event.events_for_exception(wrapper))
22
- else
23
- app_request.events.push(*Event.events_for_exception(exception))
24
- end
25
- raise
26
- ensure
27
- Storage.new(app_request.id).write(app_request.events.to_json) unless app_request.events.empty?
28
- end
29
- end
30
- end
31
- end
32
-
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module MetaRequest
6
+ module Middlewares
7
+ class AppRequestHandler
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ app_request = AppRequest.new env['action_dispatch.request_id']
14
+ app_request.current!
15
+ @app.call(env)
16
+ rescue StandardError => e
17
+ if defined?(ActionDispatch::ExceptionWrapper)
18
+ wrapper = if ActionDispatch::ExceptionWrapper.method_defined? :env
19
+ ActionDispatch::ExceptionWrapper.new(env, e)
20
+ else
21
+ ActionDispatch::ExceptionWrapper.new(env['action_dispatch.backtrace_cleaner'], e)
22
+ end
23
+ app_request.events.push(*Event.events_for_exception(wrapper))
24
+ else
25
+ app_request.events.push(*Event.events_for_exception(e))
26
+ end
27
+ raise
28
+ ensure
29
+ Storage.new(app_request.id).write(app_request.events.to_json) unless app_request.events.empty?
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,37 +1,38 @@
1
- require 'rack/contrib/response_headers'
2
-
3
- module MetaRequest
4
- module Middlewares
5
- class Headers
6
- def initialize(app, app_config)
7
- @app = app
8
- @app_config = app_config
9
- end
10
-
11
- def call(env)
12
- request_path = env['PATH_INFO']
13
- middleware = Rack::ResponseHeaders.new(@app) do |headers|
14
- headers['X-Meta-Request-Version'] = MetaRequest::VERSION unless skip?(request_path)
15
- end
16
- middleware.call(env)
17
- end
18
-
19
- private
20
-
21
- # returns true if path should be ignored (not handled by RailsPanel extension)
22
- #
23
- def skip?(path)
24
- asset?(path) || path.start_with?('/__better_errors/')
25
- end
26
-
27
- def asset?(path)
28
- @app_config.respond_to?(:assets) && path.start_with?(assets_prefix)
29
- end
30
-
31
- def assets_prefix
32
- "/#{@app_config.assets.prefix[/\A\/?(.*?)\/?\z/, 1]}/"
33
- end
34
-
35
- end
36
- end
37
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/contrib/response_headers'
4
+
5
+ module MetaRequest
6
+ module Middlewares
7
+ class Headers
8
+ def initialize(app, app_config)
9
+ @app = app
10
+ @app_config = app_config
11
+ end
12
+
13
+ def call(env)
14
+ request_path = env['PATH_INFO']
15
+ middleware = Rack::ResponseHeaders.new(@app) do |headers|
16
+ headers['X-Meta-Request-Version'] = MetaRequest::VERSION unless skip?(request_path)
17
+ end
18
+ middleware.call(env)
19
+ end
20
+
21
+ private
22
+
23
+ # returns true if path should be ignored (not handled by RailsPanel extension)
24
+ #
25
+ def skip?(path)
26
+ asset?(path) || path.start_with?('/__better_errors/')
27
+ end
28
+
29
+ def asset?(path)
30
+ @app_config.respond_to?(:assets) && path.start_with?(assets_prefix)
31
+ end
32
+
33
+ def assets_prefix
34
+ "/#{@app_config.assets.prefix[%r{\A/?(.*?)/?\z}, 1]}/"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,25 +1,27 @@
1
- module MetaRequest
2
- module Middlewares
3
- class MetaRequestHandler
4
- def initialize(app)
5
- @app = app
6
- end
7
-
8
- def call(env)
9
- request_id = env["PATH_INFO"][%r{/__meta_request/(.+)\.json$}, 1]
10
- if request_id
11
- events_json(request_id)
12
- else
13
- @app.call(env)
14
- end
15
- end
16
-
17
- private
18
-
19
- def events_json(request_id)
20
- events_json = Storage.new(request_id).read
21
- [200, { "Content-Type" => "text/plain; charset=utf-8" }, [events_json]]
22
- end
23
- end
24
- end
25
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ module Middlewares
5
+ class MetaRequestHandler
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ request_id = env['PATH_INFO'][%r{/__meta_request/(.+)\.json$}, 1]
12
+ if request_id
13
+ events_json(request_id)
14
+ else
15
+ @app.call(env)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def events_json(request_id)
22
+ events_json = Storage.new(request_id).read
23
+ [200, { 'Content-Type' => 'text/plain; charset=utf-8' }, [events_json]]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,7 +1,9 @@
1
- module MetaRequest
2
- module Middlewares
3
- autoload :Headers, "meta_request/middlewares/headers"
4
- autoload :AppRequestHandler, "meta_request/middlewares/app_request_handler"
5
- autoload :MetaRequestHandler, "meta_request/middlewares/meta_request_handler"
6
- end
7
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ module Middlewares
5
+ autoload :Headers, 'meta_request/middlewares/headers'
6
+ autoload :AppRequestHandler, 'meta_request/middlewares/app_request_handler'
7
+ autoload :MetaRequestHandler, 'meta_request/middlewares/meta_request_handler'
8
+ end
9
+ end
@@ -1,29 +1,27 @@
1
- require 'rails/railtie'
2
-
3
- module MetaRequest
4
- class Railtie < ::Rails::Railtie
5
-
6
- initializer 'meta_request.inject_middlewares' do |app|
7
- app.middleware.use Middlewares::MetaRequestHandler
8
-
9
- if defined? ActionDispatch::DebugExceptions
10
- app.middleware.insert_before ActionDispatch::DebugExceptions, Middlewares::Headers, app.config
11
- else
12
- app.middleware.use Middlewares::Headers, app.config
13
- end
14
-
15
- app.middleware.use Middlewares::AppRequestHandler
16
- end
17
-
18
- initializer 'meta_request.log_interceptor' do
19
- Rails.logger.extend(LogInterceptor) if Rails.logger
20
- end
21
-
22
- initializer 'meta_request.subscribe_to_notifications' do
23
- AppNotifications.subscribe
24
- end
25
-
26
- end
27
- end
28
-
29
-
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/railtie'
4
+
5
+ module MetaRequest
6
+ class Railtie < ::Rails::Railtie
7
+ initializer 'meta_request.inject_middlewares' do |app|
8
+ app.middleware.use Middlewares::MetaRequestHandler
9
+
10
+ if defined? ActionDispatch::DebugExceptions
11
+ app.middleware.insert_before ActionDispatch::DebugExceptions, Middlewares::Headers, app.config
12
+ else
13
+ app.middleware.use Middlewares::Headers, app.config
14
+ end
15
+
16
+ app.middleware.use Middlewares::AppRequestHandler
17
+ end
18
+
19
+ initializer 'meta_request.log_interceptor' do
20
+ Rails.logger&.extend(LogInterceptor)
21
+ end
22
+
23
+ initializer 'meta_request.subscribe_to_notifications' do
24
+ AppNotifications.subscribe
25
+ end
26
+ end
27
+ end
@@ -1,43 +1,45 @@
1
- module MetaRequest
2
- class Storage
3
- attr_reader :key
4
-
5
- def initialize(key)
6
- @key = key
7
- end
8
-
9
- def write(value)
10
- FileUtils.mkdir_p dir_path
11
- File.open(json_file, 'wb') { |file| file.write(value) }
12
- maintain_file_pool(10)
13
- end
14
-
15
- def read
16
- File.read(json_file)
17
- end
18
-
19
- private
20
-
21
- def maintain_file_pool(size)
22
- files = Dir["#{dir_path}/*.json"]
23
- files = files.sort_by { |f| -file_ctime(f) }
24
- (files[size..-1] || []).each do |file|
25
- FileUtils.rm_f(file)
26
- end
27
- end
28
-
29
- def file_ctime(file)
30
- File.stat(file).ctime.to_i
31
- rescue Errno::ENOENT
32
- 0
33
- end
34
-
35
- def json_file
36
- File.join(dir_path, "#{key}.json")
37
- end
38
-
39
- def dir_path
40
- File.join(Rails.root, 'tmp', 'data', 'meta_request')
41
- end
42
- end
43
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ class Storage
5
+ attr_reader :key
6
+
7
+ def initialize(key)
8
+ @key = key
9
+ end
10
+
11
+ def write(value)
12
+ FileUtils.mkdir_p dir_path
13
+ File.open(json_file, 'wb') { |file| file.write(value) }
14
+ maintain_file_pool(MetaRequest.config.storage_pool_size)
15
+ end
16
+
17
+ def read
18
+ File.read(json_file)
19
+ end
20
+
21
+ private
22
+
23
+ def maintain_file_pool(size)
24
+ files = Dir["#{dir_path}/*.json"]
25
+ files = files.sort_by { |f| -file_ctime(f) }
26
+ (files[size..-1] || []).each do |file|
27
+ FileUtils.rm_f(file)
28
+ end
29
+ end
30
+
31
+ def file_ctime(file)
32
+ File.stat(file).ctime.to_i
33
+ rescue Errno::ENOENT
34
+ 0
35
+ end
36
+
37
+ def json_file
38
+ File.join(dir_path, "#{key}.json")
39
+ end
40
+
41
+ def dir_path
42
+ File.join(Rails.root, 'tmp', 'data', 'meta_request')
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ module Utils
5
+ module_function
6
+
7
+ def dev_callsite(caller)
8
+ app_line = caller.detect { |c| c.start_with? MetaRequest.rails_root }
9
+ return nil unless app_line
10
+
11
+ _, filename, _, line, _, method = app_line.split(/^(.*?)(:(\d+))(:in `(.*)')?$/)
12
+
13
+ {
14
+ filename: sub_source_path(filename),
15
+ line: line.to_i,
16
+ method: method
17
+ }
18
+ end
19
+
20
+ def sub_source_path(path)
21
+ rails_root = MetaRequest.rails_root
22
+ source_path = MetaRequest.config.source_path
23
+ return path if rails_root == source_path
24
+
25
+ path.sub(rails_root, source_path)
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,5 @@
1
- module MetaRequest
2
- VERSION = '0.6.0'
3
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ VERSION = Gem.loaded_specs['meta_request'].version.to_s
5
+ end
data/lib/meta_request.rb CHANGED
@@ -1,21 +1,29 @@
1
- module MetaRequest
2
- autoload :VERSION, "meta_request/version"
3
- autoload :Event, "meta_request/event"
4
- autoload :AppRequest, "meta_request/app_request"
5
- autoload :Storage, "meta_request/storage"
6
- autoload :Middlewares, "meta_request/middlewares"
7
- autoload :LogInterceptor, "meta_request/log_interceptor"
8
- autoload :AppNotifications, "meta_request/app_notifications"
9
-
10
- def self.logger
11
- @@logger ||= Logger.new(File.join(Rails.root, 'log', 'meta_request.log'))
12
- end
13
-
14
- # stash a frozen copy away so we're not allocating a new string over and over
15
- # again in AppNotifications and LogInterceptor
16
- def self.rails_root
17
- @@rails_root ||= Rails.root.to_s.freeze
18
- end
19
- end
20
-
21
- require "meta_request/railtie"
1
+ # frozen_string_literal: true
2
+
3
+ module MetaRequest
4
+ autoload :VERSION, 'meta_request/version'
5
+ autoload :Config, 'meta_request/config'
6
+ autoload :Event, 'meta_request/event'
7
+ autoload :AppRequest, 'meta_request/app_request'
8
+ autoload :Storage, 'meta_request/storage'
9
+ autoload :Middlewares, 'meta_request/middlewares'
10
+ autoload :LogInterceptor, 'meta_request/log_interceptor'
11
+ autoload :AppNotifications, 'meta_request/app_notifications'
12
+ autoload :Utils, 'meta_request/utils'
13
+
14
+ def self.config
15
+ @config ||= Config.new
16
+ end
17
+
18
+ def self.configure
19
+ yield config
20
+ end
21
+
22
+ # stash a frozen copy away so we're not allocating a new string over and over
23
+ # again in AppNotifications and LogInterceptor
24
+ def self.rails_root
25
+ @rails_root ||= Rails.root.to_s.freeze
26
+ end
27
+ end
28
+
29
+ require 'meta_request/railtie'
metadata CHANGED
@@ -1,75 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meta_request
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dejan Simic
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-06 00:00:00.000000000 Z
11
+ date: 2021-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: railties
14
+ name: rack-contrib
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.0.0
19
+ version: '1.1'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '6'
22
+ version: '3'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 3.0.0
29
+ version: '1.1'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '6'
32
+ version: '3'
33
33
  - !ruby/object:Gem::Dependency
34
- name: rack-contrib
34
+ name: railties
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: '1.1'
39
+ version: 3.0.0
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '3'
42
+ version: '7'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - ">="
48
48
  - !ruby/object:Gem::Version
49
- version: '1.1'
49
+ version: 3.0.0
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '3'
52
+ version: '7'
53
53
  - !ruby/object:Gem::Dependency
54
- name: callsite
54
+ name: rspec
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: '0.0'
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 0.0.11
63
- type: :runtime
59
+ version: 3.8.0
60
+ type: :development
64
61
  prerelease: false
65
62
  version_requirements: !ruby/object:Gem::Requirement
66
63
  requirements:
67
64
  - - "~>"
68
65
  - !ruby/object:Gem::Version
69
- version: '0.0'
70
- - - ">="
66
+ version: 3.8.0
67
+ - !ruby/object:Gem::Dependency
68
+ name: rubocop
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: 0.74.0
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
71
79
  - !ruby/object:Gem::Version
72
- version: 0.0.11
80
+ version: 0.74.0
73
81
  description: Supporting gem for Rails Panel (Google Chrome extension for Rails development)
74
82
  email: desimic@gmail.com
75
83
  executables: []
@@ -80,6 +88,7 @@ files:
80
88
  - lib/meta_request.rb
81
89
  - lib/meta_request/app_notifications.rb
82
90
  - lib/meta_request/app_request.rb
91
+ - lib/meta_request/config.rb
83
92
  - lib/meta_request/event.rb
84
93
  - lib/meta_request/log_interceptor.rb
85
94
  - lib/meta_request/middlewares.rb
@@ -88,12 +97,13 @@ files:
88
97
  - lib/meta_request/middlewares/meta_request_handler.rb
89
98
  - lib/meta_request/railtie.rb
90
99
  - lib/meta_request/storage.rb
100
+ - lib/meta_request/utils.rb
91
101
  - lib/meta_request/version.rb
92
102
  homepage: https://github.com/dejan/rails_panel/tree/master/meta_request
93
103
  licenses:
94
104
  - MIT
95
105
  metadata: {}
96
- post_install_message:
106
+ post_install_message:
97
107
  rdoc_options: []
98
108
  require_paths:
99
109
  - lib
@@ -108,9 +118,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
118
  - !ruby/object:Gem::Version
109
119
  version: '0'
110
120
  requirements: []
111
- rubyforge_project:
112
- rubygems_version: 2.6.14
113
- signing_key:
121
+ rubygems_version: 3.2.22
122
+ signing_key:
114
123
  specification_version: 4
115
124
  summary: Request your Rails request
116
125
  test_files: []