asana_exception_notifier 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.codeclimate.yml +26 -0
- data/.reek +11 -0
- data/.rubocop.yml +76 -0
- data/.travis.yml +16 -0
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +180 -0
- data/LICENSE +20 -0
- data/README.md +225 -0
- data/Rakefile +37 -0
- data/asana_exception_notifier.gemspec +48 -0
- data/examples/sinatra/Gemfile +7 -0
- data/examples/sinatra/Gemfile.lock +124 -0
- data/examples/sinatra/Procfile +1 -0
- data/examples/sinatra/README.md +14 -0
- data/examples/sinatra/config.ru +3 -0
- data/examples/sinatra/sinatra_app.rb +46 -0
- data/init.rb +1 -0
- data/lib/asana_exception_notifier/classes/asana.rb +95 -0
- data/lib/asana_exception_notifier/classes/error_page.rb +134 -0
- data/lib/asana_exception_notifier/helpers/application_helper.rb +286 -0
- data/lib/asana_exception_notifier/initializers/zip.rb +14 -0
- data/lib/asana_exception_notifier/note_templates/asana_exception_notifier.html.erb +82 -0
- data/lib/asana_exception_notifier/note_templates/asana_exception_notifier.text.erb +24 -0
- data/lib/asana_exception_notifier/request/client.rb +85 -0
- data/lib/asana_exception_notifier/request/core.rb +132 -0
- data/lib/asana_exception_notifier/request/middleware.rb +41 -0
- data/lib/asana_exception_notifier/version.rb +27 -0
- data/lib/asana_exception_notifier.rb +45 -0
- data/lib/generators/asana_exception_notifier/install_generator.rb +14 -0
- data/lib/generators/asana_exception_notifier/templates/asana_exception_notifier.rb +20 -0
- data/spec/lib/asana_exception_notifier/classes/asana_spec.rb +23 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/test_notification.rb +20 -0
- metadata +467 -0
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
require 'coveralls/rake/task'
|
5
|
+
require 'yard'
|
6
|
+
Coveralls::RakeTask.new
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
default_options = ['--colour']
|
10
|
+
default_options.concat(['--backtrace', '--fail-fast']) if ENV['DEBUG']
|
11
|
+
spec.rspec_opts = default_options
|
12
|
+
end
|
13
|
+
|
14
|
+
YARD::Config.options[:load_plugins] = true
|
15
|
+
YARD::Config.load_plugins
|
16
|
+
|
17
|
+
YARD::Rake::YardocTask.new do |t|
|
18
|
+
t.files = ['lib/**/*.rb', 'spec/**/*_spec.rb'] # optional
|
19
|
+
t.options = ['--any', '--extra', '--opts', '--markup-provider=redcarpet', '--markup=markdown', '--debug'] # optional
|
20
|
+
t.stats_options = ['--list-undoc'] # optional
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Default: run the unit tests.'
|
24
|
+
task default: [:all]
|
25
|
+
|
26
|
+
desc 'Test the plugin under all supported Rails versions.'
|
27
|
+
task :all do |_t|
|
28
|
+
if ENV['TRAVIS']
|
29
|
+
exec('bundle exec rake spec && bundle exec rake coveralls:push')
|
30
|
+
else
|
31
|
+
exec('bundle exec rake spec')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
task :docs do
|
36
|
+
exec('bundle exec inch --pedantic && bundle exec yard --list-undoc')
|
37
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path('../lib/asana_exception_notifier/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'asana_exception_notifier'
|
5
|
+
s.version = AsanaExceptionNotifier.gem_version
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.summary = 'Simple ruby implementation to send notifications to Asana
|
8
|
+
when a exception happens in Rails or Rack-based apps by creating a task and uploading exception details to the task'
|
9
|
+
s.email = 'raoul_ice@yahoo.com'
|
10
|
+
s.homepage = 'http://github.com/bogdanRada/asana_exception_notifier'
|
11
|
+
s.description = 'Simple ruby implementation to send notifications to Asana
|
12
|
+
when a exception happens in Rails or Rack-based apps by creating a task and uploading exception details to the task using zip archives'
|
13
|
+
s.authors = ['bogdanRada']
|
14
|
+
s.date = Date.today
|
15
|
+
|
16
|
+
s.licenses = ['MIT']
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = s.files.grep(/^(spec)/)
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
|
21
|
+
s.required_ruby_version = '>= 2.0'
|
22
|
+
s.required_rubygems_version = '>= 2.5'
|
23
|
+
s.metadata = {
|
24
|
+
'source_code' => s.homepage,
|
25
|
+
'bug_tracker' => "#{s.homepage}/issues"
|
26
|
+
}
|
27
|
+
|
28
|
+
s.add_runtime_dependency 'activesupport', '>= 4.0', '< 5'
|
29
|
+
s.add_runtime_dependency 'em-http-request', '~> 1.1', '>= 1.1.2'
|
30
|
+
s.add_runtime_dependency 'eventmachine', '~> 1.0', '>= 1.0.7'
|
31
|
+
s.add_runtime_dependency 'exception_notification', '~> 4.1', '>= 4.1.4'
|
32
|
+
s.add_runtime_dependency 'multipart_body', '~> 0.2', '>= 0.2.1'
|
33
|
+
s.add_runtime_dependency 'tilt', '>= 1.4', '< 3'
|
34
|
+
s.add_runtime_dependency 'rack', '~> 1.6', '>= 1.6'
|
35
|
+
s.add_runtime_dependency 'rubyzip', '~> 1.0', '>= 1.0.0' # will load new rubyzip version
|
36
|
+
s.add_runtime_dependency 'zip-zip', '~> 0.3', '>= 0.3' # will load compatibility for old rubyzip API
|
37
|
+
s.add_runtime_dependency 'sys-uname', '~> 1.0', '>= 1.0.2'
|
38
|
+
|
39
|
+
s.add_development_dependency 'rspec', '~> 3.4', '>= 3.4'
|
40
|
+
s.add_development_dependency 'simplecov', '~> 0.10', '>= 0.10'
|
41
|
+
s.add_development_dependency 'simplecov-summary', '~> 0.0.4', '>= 0.0.4'
|
42
|
+
s.add_development_dependency 'coveralls', '~> 0.7', '>= 0.7'
|
43
|
+
s.add_development_dependency 'rake', '~> 10.5', '>= 10.5'
|
44
|
+
s.add_development_dependency 'yard', '~> 0.8', '>= 0.8.7'
|
45
|
+
s.add_development_dependency 'redcarpet', '~> 3.3', '>= 3.3'
|
46
|
+
s.add_development_dependency 'github-markup', '~> 1.3', '>= 1.3.3'
|
47
|
+
s.add_development_dependency 'inch', '~> 0.6', '>= 0.6'
|
48
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../../
|
3
|
+
specs:
|
4
|
+
asana_exception_notifier (0.0.1)
|
5
|
+
activesupport (>= 4.0, < 5)
|
6
|
+
em-http-request (~> 1.1, >= 1.1.2)
|
7
|
+
eventmachine (~> 1.0, >= 1.0.7)
|
8
|
+
exception_notification (~> 4.1, >= 4.1.4)
|
9
|
+
multipart_body (~> 0.2, >= 0.2.1)
|
10
|
+
rack (~> 1.6, >= 1.6)
|
11
|
+
rubyzip (~> 1.0, >= 1.0.0)
|
12
|
+
sys-uname (~> 1.0, >= 1.0.2)
|
13
|
+
tilt (>= 1.4, < 3)
|
14
|
+
zip-zip (~> 0.3, >= 0.3)
|
15
|
+
|
16
|
+
GEM
|
17
|
+
remote: https://rubygems.org/
|
18
|
+
specs:
|
19
|
+
actionmailer (4.2.5.1)
|
20
|
+
actionpack (= 4.2.5.1)
|
21
|
+
actionview (= 4.2.5.1)
|
22
|
+
activejob (= 4.2.5.1)
|
23
|
+
mail (~> 2.5, >= 2.5.4)
|
24
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
25
|
+
actionpack (4.2.5.1)
|
26
|
+
actionview (= 4.2.5.1)
|
27
|
+
activesupport (= 4.2.5.1)
|
28
|
+
rack (~> 1.6)
|
29
|
+
rack-test (~> 0.6.2)
|
30
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
31
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
32
|
+
actionview (4.2.5.1)
|
33
|
+
activesupport (= 4.2.5.1)
|
34
|
+
builder (~> 3.1)
|
35
|
+
erubis (~> 2.7.0)
|
36
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
37
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
38
|
+
activejob (4.2.5.1)
|
39
|
+
activesupport (= 4.2.5.1)
|
40
|
+
globalid (>= 0.3.0)
|
41
|
+
activesupport (4.2.5.1)
|
42
|
+
i18n (~> 0.7)
|
43
|
+
json (~> 1.7, >= 1.7.7)
|
44
|
+
minitest (~> 5.1)
|
45
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
46
|
+
tzinfo (~> 1.1)
|
47
|
+
addressable (2.4.0)
|
48
|
+
builder (3.2.2)
|
49
|
+
cookiejar (0.3.0)
|
50
|
+
daemons (1.2.3)
|
51
|
+
em-http-request (1.1.3)
|
52
|
+
addressable (>= 2.3.4)
|
53
|
+
cookiejar (<= 0.3.0)
|
54
|
+
em-socksify (>= 0.3)
|
55
|
+
eventmachine (>= 1.0.3)
|
56
|
+
http_parser.rb (>= 0.6.0)
|
57
|
+
em-socksify (0.3.1)
|
58
|
+
eventmachine (>= 1.0.0.beta.4)
|
59
|
+
erubis (2.7.0)
|
60
|
+
eventmachine (1.0.9.1)
|
61
|
+
exception_notification (4.1.4)
|
62
|
+
actionmailer (~> 4.0)
|
63
|
+
activesupport (~> 4.0)
|
64
|
+
ffi (1.9.10)
|
65
|
+
foreman (0.78.0)
|
66
|
+
thor (~> 0.19.1)
|
67
|
+
globalid (0.3.6)
|
68
|
+
activesupport (>= 4.1.0)
|
69
|
+
http_parser.rb (0.6.0)
|
70
|
+
i18n (0.7.0)
|
71
|
+
json (1.8.3)
|
72
|
+
loofah (2.0.3)
|
73
|
+
nokogiri (>= 1.5.9)
|
74
|
+
mail (2.6.3)
|
75
|
+
mime-types (>= 1.16, < 3)
|
76
|
+
mime-types (2.99)
|
77
|
+
mini_portile2 (2.0.0)
|
78
|
+
minitest (5.8.4)
|
79
|
+
multipart_body (0.2.1)
|
80
|
+
nokogiri (1.6.7.2)
|
81
|
+
mini_portile2 (~> 2.0.0.rc2)
|
82
|
+
rack (1.6.4)
|
83
|
+
rack-protection (1.5.3)
|
84
|
+
rack
|
85
|
+
rack-test (0.6.3)
|
86
|
+
rack (>= 1.0)
|
87
|
+
rails-deprecated_sanitizer (1.0.3)
|
88
|
+
activesupport (>= 4.2.0.alpha)
|
89
|
+
rails-dom-testing (1.0.7)
|
90
|
+
activesupport (>= 4.2.0.beta, < 5.0)
|
91
|
+
nokogiri (~> 1.6.0)
|
92
|
+
rails-deprecated_sanitizer (>= 1.0.1)
|
93
|
+
rails-html-sanitizer (1.0.3)
|
94
|
+
loofah (~> 2.0)
|
95
|
+
rubyzip (1.1.7)
|
96
|
+
sinatra (1.4.7)
|
97
|
+
rack (~> 1.5)
|
98
|
+
rack-protection (~> 1.4)
|
99
|
+
tilt (>= 1.3, < 3)
|
100
|
+
sys-uname (1.0.2)
|
101
|
+
ffi (>= 1.0.0)
|
102
|
+
thin (1.5.1)
|
103
|
+
daemons (>= 1.0.9)
|
104
|
+
eventmachine (>= 0.12.6)
|
105
|
+
rack (>= 1.0.0)
|
106
|
+
thor (0.19.1)
|
107
|
+
thread_safe (0.3.5)
|
108
|
+
tilt (2.0.2)
|
109
|
+
tzinfo (1.2.2)
|
110
|
+
thread_safe (~> 0.1)
|
111
|
+
zip-zip (0.3)
|
112
|
+
rubyzip (>= 1.0.0)
|
113
|
+
|
114
|
+
PLATFORMS
|
115
|
+
ruby
|
116
|
+
|
117
|
+
DEPENDENCIES
|
118
|
+
asana_exception_notifier!
|
119
|
+
foreman
|
120
|
+
sinatra (~> 1.4)
|
121
|
+
thin (~> 1.5.1)
|
122
|
+
|
123
|
+
BUNDLED WITH
|
124
|
+
1.11.2
|
@@ -0,0 +1 @@
|
|
1
|
+
web: bundle exec thin start --port 3000
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Using Exception Notification with Sinatra
|
2
|
+
=========================================
|
3
|
+
|
4
|
+
Quick start
|
5
|
+
-----------
|
6
|
+
|
7
|
+
```
|
8
|
+
git clone git@github.com:bogdanRada/asana_exception_notifier.git
|
9
|
+
cd exception_notification/examples/sinatra
|
10
|
+
bundle install
|
11
|
+
bundle exec foreman start
|
12
|
+
```
|
13
|
+
|
14
|
+
The last command starts the sinatra app itself. Thus, visit [http://localhost:1080/](http://localhost:1080/) to check the asana notification is sent and, in a separated tab, visit [Asana.com](http://asana.com) and cause some errors. For more info, use the [source](https://github.com/bogdanRada/asana_exception_notifier/blob/master/examples/sinatra/sinatra_app.rb).
|
@@ -0,0 +1,46 @@
|
|
1
|
+
$stdout.sync = true
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
require 'bundler/setup'
|
5
|
+
ENV['RACK_ENV'] ||= ENV['RAILS_ENV'].present? ? ENV['RAILS_ENV'] : 'development'
|
6
|
+
Bundler.require :default, (ENV['RACK_ENV'] || 'development').to_sym
|
7
|
+
|
8
|
+
|
9
|
+
class SinatraApp < Sinatra::Base
|
10
|
+
use Rack::Config do |env|
|
11
|
+
env["action_dispatch.parameter_filter"] = [:password] # This is highly recommended. It will prevent the ExceptionNotification email from including your users' passwords
|
12
|
+
end
|
13
|
+
|
14
|
+
use ExceptionNotification::Rack,
|
15
|
+
:asana => {
|
16
|
+
asana_api_key: ENV['ASANA_API_KEY'],
|
17
|
+
workspace: ENV['ASANA_WORKSPACE_ID'],
|
18
|
+
assignee: 'me',
|
19
|
+
assignee_status: 'today', # 'today'
|
20
|
+
due_at: Time.now.iso8601,
|
21
|
+
due_on: nil,
|
22
|
+
hearted: false,
|
23
|
+
hearts: [],
|
24
|
+
projects: [],
|
25
|
+
followers: [],
|
26
|
+
memberships: [],
|
27
|
+
tags: [],
|
28
|
+
name: nil,
|
29
|
+
notes: '',
|
30
|
+
template_path: nil
|
31
|
+
}
|
32
|
+
|
33
|
+
get '/' do
|
34
|
+
raise StandardError, "ERROR: #{params[:error]}" unless params[:error].blank?
|
35
|
+
'Everything is fine! Now, lets break things clicking <a href="/?error=ops"> here </a>. Dont forget to see the asana tasks at <a href="http://asana.com">Asana</a> !'
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/background_notification' do
|
39
|
+
begin
|
40
|
+
1/0
|
41
|
+
rescue Exception => e
|
42
|
+
ExceptionNotifier.notify_exception(e, :data => {:msg => "Cannot divide by zero!"})
|
43
|
+
end
|
44
|
+
'Check notification at <a href="http://asana.com">Asana</a>.'
|
45
|
+
end
|
46
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'asana_exception_notifier'
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require_relative '../helpers/application_helper'
|
2
|
+
require_relative '../request/client'
|
3
|
+
require_relative '../request/middleware'
|
4
|
+
# class used for connecting to github api and retrieves information about repository
|
5
|
+
#
|
6
|
+
# @!attribute callback
|
7
|
+
# @return [Proc] The callback that is executed after the info is fetched from Github API
|
8
|
+
module ExceptionNotifier
|
9
|
+
# module that is used for formatting numbers using metrics
|
10
|
+
class AsanaNotifier < ExceptionNotifier::BaseNotifier
|
11
|
+
include AsanaExceptionNotifier::ApplicationHelper
|
12
|
+
# the base url to which the API will connect for fetching information about gems
|
13
|
+
attr_reader :initial_options, :default_options
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
execute_with_rescue do
|
17
|
+
super
|
18
|
+
@initial_options = options.symbolize_keys
|
19
|
+
options = @initial_options.reject { |_key, value| value.blank? }
|
20
|
+
parse_options(options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(exception, options = {})
|
25
|
+
execute_with_rescue do
|
26
|
+
ensure_eventmachine_running do
|
27
|
+
EM::HttpRequest.use AsanaExceptionNotifier::Request::Middleware if ENV['DEBUG_ASANA_EXCEPTION_NOTIFIER']
|
28
|
+
error_page = AsanaExceptionNotifier::ErrorPage.new(template_path, exception, options)
|
29
|
+
create_asana_task(error_page) if active?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def active?
|
35
|
+
@default_options.fetch(:asana_api_key, nil).present? && @default_options.fetch(:workspace, nil).present?
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def parse_options(options)
|
41
|
+
options = options.symbolize_keys.reject { |key, _value| !permitted_options.key?(key) }
|
42
|
+
@default_options = permitted_options.merge(options).reject { |_key, value| value.blank? }
|
43
|
+
end
|
44
|
+
|
45
|
+
def template_path
|
46
|
+
template_path = @default_options.fetch(:template_path, nil)
|
47
|
+
template_path.blank? ? default_template_path : template_path_exist(File.expand_path(template_path))
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_request_options(error_page)
|
51
|
+
@default_options.except(:asana_api_key, :template_path).merge(
|
52
|
+
name: @default_options.fetch(:name, nil) || "[AsanaExceptionNotifier] #{error_page.exception_data[:message]}",
|
53
|
+
notes: @default_options.fetch(:notes, nil) || error_page.render_template(File.join(template_dir, 'asana_exception_notifier.text.erb')),
|
54
|
+
workspace: @default_options.fetch(:workspace, nil).to_i
|
55
|
+
).symbolize_keys!
|
56
|
+
end
|
57
|
+
|
58
|
+
# This method fetches data from Github api and returns the size in
|
59
|
+
#
|
60
|
+
# @return [void]
|
61
|
+
def create_asana_task(error_page)
|
62
|
+
AsanaExceptionNotifier::Request::Client.new(@default_options.fetch(:asana_api_key, nil),
|
63
|
+
'https://app.asana.com/api/1.0/tasks',
|
64
|
+
'http_method' => 'post',
|
65
|
+
'em_request' => { body: build_request_options(error_page) },
|
66
|
+
'action' => 'creation'
|
67
|
+
) do |http_response|
|
68
|
+
ensure_eventmachine_running do
|
69
|
+
upload_log_file_to_task(error_page, http_response.fetch('data', {}))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def upload_log_file_to_task(error_page, task_data)
|
75
|
+
archives = error_page.fetch_archives
|
76
|
+
archives.each do |zip|
|
77
|
+
upload_archive(zip, task_data)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def upload_archive(zip, task_data)
|
82
|
+
return if task_data.blank?
|
83
|
+
body = multipart_file_upload_details(zip)
|
84
|
+
AsanaExceptionNotifier::Request::Client.new(@default_options.fetch(:asana_api_key, nil),
|
85
|
+
"https://app.asana.com/api/1.0/tasks/#{task_data['id']}/attachments",
|
86
|
+
'http_method' => 'post',
|
87
|
+
'em_request' => body,
|
88
|
+
'request_name' => zip,
|
89
|
+
'action' => 'upload'
|
90
|
+
) do |_http_response|
|
91
|
+
FileUtils.rm_rf([zip])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require_relative '../helpers/application_helper'
|
2
|
+
module AsanaExceptionNotifier
|
3
|
+
# class used for rendering the template for exception
|
4
|
+
class ErrorPage
|
5
|
+
include AsanaExceptionNotifier::ApplicationHelper
|
6
|
+
|
7
|
+
attr_reader :template_path, :exception, :options, :boundary, :template_details, :env, :request, :tempfile, :template_params, :content
|
8
|
+
|
9
|
+
def initialize(template_path, exception, options)
|
10
|
+
@template_path = template_path
|
11
|
+
@exception = exception
|
12
|
+
@options = options.symbolize_keys
|
13
|
+
@template_details = setup_template_details
|
14
|
+
@env = (@options[:env] || ENV.to_h).stringify_keys
|
15
|
+
@request = action_dispatch? ? ActionDispatch::Request.new(@env) : Rack::Request.new(@env)
|
16
|
+
@timestamp = Time.now
|
17
|
+
parse_exception_options
|
18
|
+
end
|
19
|
+
|
20
|
+
def action_dispatch?
|
21
|
+
defined?(ActionDispatch::Request)
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup_template_details
|
25
|
+
template_extension = @template_path.scan(/\.(\w+)\.?(.*)?/)[0][0]
|
26
|
+
get_extension_and_name_from_file(@template_path).merge(
|
27
|
+
template_extension: template_extension
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_exception_options
|
32
|
+
@template_params ||= {
|
33
|
+
server: Socket.gethostname,
|
34
|
+
exception: @exception,
|
35
|
+
request: @request,
|
36
|
+
environment: action_dispatch? ? @request.filtered_env : @env,
|
37
|
+
rails_root: defined?(Rails) ? Rails.root : nil,
|
38
|
+
process: $PROCESS_ID,
|
39
|
+
data: (@env.blank? ? {} : @env.fetch(:'exception_notifier.exception_data', {})).merge(@options[:data] || {}),
|
40
|
+
exception_data: exception_data,
|
41
|
+
request_data: setup_env_params,
|
42
|
+
uname: Sys::Uname.uname,
|
43
|
+
timestamp: @timestamp,
|
44
|
+
pwd: File.expand_path($PROGRAM_NAME)
|
45
|
+
}.merge(@options).reject { |_key, value| value.blank? }
|
46
|
+
end
|
47
|
+
|
48
|
+
def exception_data
|
49
|
+
{
|
50
|
+
error_class: @exception.class.to_s,
|
51
|
+
message: @exception.respond_to?(:message) ? @exception.message : exception.inspect,
|
52
|
+
backtrace: @exception.respond_to?(:backtrace) ? @exception.backtrace : '',
|
53
|
+
cause: @exception.respond_to?(:cause) ? @exception.cause : ''
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def setup_env_params
|
58
|
+
{
|
59
|
+
url: action_dispatch? ? @request.original_url : @request.path_info,
|
60
|
+
referrer: @request.referer,
|
61
|
+
http_method: action_dispatch? ? @request.method : @request.request_method,
|
62
|
+
ip_address: action_dispatch? ? @request.remote_ip : @request.ip,
|
63
|
+
parameters: action_dispatch? ? @request.filtered_parameters : request_params,
|
64
|
+
session: @request.session,
|
65
|
+
cookies: @request.cookies,
|
66
|
+
user_agent: @request.user_agent
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def request_params
|
71
|
+
@request.params
|
72
|
+
rescue
|
73
|
+
{}
|
74
|
+
end
|
75
|
+
|
76
|
+
def fieldsets_links
|
77
|
+
fieldsets.map { |key, _value| link_helper(key.to_s) }.join(' | ')
|
78
|
+
end
|
79
|
+
|
80
|
+
def fetch_fieldsets(hash, links = {}, prefix = nil)
|
81
|
+
return unless hash.is_a?(Hash)
|
82
|
+
hash.each do |key, value|
|
83
|
+
if value.is_a?(Hash)
|
84
|
+
fetch_fieldsets(value, links, key)
|
85
|
+
else
|
86
|
+
add_to_links(links, prefix, key: key, value: value)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
links
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_to_links(links, prefix, options = {})
|
93
|
+
expected_value = parse_fieldset_value(options)
|
94
|
+
return unless expected_value.present?
|
95
|
+
prefix_name = set_fieldset_key(links, prefix || 'basic_info')
|
96
|
+
links[prefix_name][options[:key]] = expected_value
|
97
|
+
end
|
98
|
+
|
99
|
+
def fieldsets
|
100
|
+
@fieldsets ||= fetch_fieldsets(parse_exception_options).except(:env)
|
101
|
+
end
|
102
|
+
|
103
|
+
def render_template(template = nil)
|
104
|
+
execute_with_rescue do
|
105
|
+
current_template = template.present? ? template : @template_path
|
106
|
+
Tilt.new(current_template).render(self, @template_params.stringify_keys)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def create_tempfile(output = render_template)
|
111
|
+
tempfile = Tempfile.new([SecureRandom.uuid, ".#{@template_details[:template_extension]}"], encoding: 'utf-8')
|
112
|
+
tempfile.write(output)
|
113
|
+
tempfile.close
|
114
|
+
details = tempfile_details(tempfile)
|
115
|
+
[details[:filename], details[:path]]
|
116
|
+
end
|
117
|
+
|
118
|
+
def fetch_archives(output = render_template)
|
119
|
+
return [] if output.blank?
|
120
|
+
filename, path = create_tempfile(output)
|
121
|
+
archive = compress_files(File.dirname(path), filename, [path])
|
122
|
+
remove_tempfile(path)
|
123
|
+
split_archive(archive, "part_#{filename}", 1024 * 1024 * 100)
|
124
|
+
end
|
125
|
+
|
126
|
+
def remove_tempfile(path)
|
127
|
+
if ENV['DEBUG_ASANA_TEMPLATE']
|
128
|
+
logger.debug(path)
|
129
|
+
else
|
130
|
+
FileUtils.rm_rf([path])
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|