asana_exception_notifier 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a170f37a6fd2fb5b9b425575e3a57b66c5b59d03
4
- data.tar.gz: 9442fd0a1ec8c08d44bb1cdc37779a5710bacfe6
3
+ metadata.gz: d49c3e2401adece7dbc4761eaacf9e40b5bd7cf4
4
+ data.tar.gz: 3ac6129faa6145a09c70c019550ab6f018c92460
5
5
  SHA512:
6
- metadata.gz: 3b25485c8d9c9ca896b708ed9784ba214028670550584391aa12fdd083b441ba72357ce5bf9a8faf68f7618b74dc827ec89ce1a7daf6ea05366cd05ec6fb56c0
7
- data.tar.gz: 3591d5bb1dc40e135437045ae8e38dc78a1e9349a47cc3b493578e3ed777d26182639544c9d51f671f6e6b4d3313770ecc5573dccdd7bd05b0db5cdb861bd9dc
6
+ metadata.gz: 5c1cdaccb5e3ac31b60fae42eb0f1822df3c2631b86899824b0c06fbe5d2fc663b75fc2e9d1f73a4f41f60d3c4812808f52fd37d624e1c9a3eea18d70e3ef234
7
+ data.tar.gz: 93756e13405772450fe88f912170b1ec599a2d4fe021f5c6ce0f74ef8ed97204aff6bffb4ef3ef8f04979f8905538f3425dd4522a4464d4654b2ef9cdfbbac98
@@ -26,8 +26,8 @@ Gem::Specification.new do |s|
26
26
  }
27
27
 
28
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'
29
+ s.add_runtime_dependency 'asana', '~> 0.5', '>= 0.5.0'
30
+ s.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.2'
31
31
  s.add_runtime_dependency 'exception_notification', '~> 4.1', '>= 4.1.4'
32
32
  s.add_runtime_dependency 'multipart_body', '~> 0.2', '>= 0.2.1'
33
33
  s.add_runtime_dependency 'tilt', '>= 1.4', '< 3'
@@ -1,6 +1,4 @@
1
1
  require_relative '../helpers/application_helper'
2
- require_relative '../request/client'
3
- require_relative '../request/middleware'
4
2
  # class used for connecting to github api and retrieves information about repository
5
3
  #
6
4
  # @!attribute callback
@@ -18,8 +16,21 @@ module ExceptionNotifier
18
16
  parse_options(@initial_options)
19
17
  end
20
18
 
19
+
20
+ def asana_client
21
+ @asana_client = Asana::Client.new do |c|
22
+ c.authentication :access_token, asana_api_key
23
+ c.debug_mode
24
+ c.faraday_adapter :typhoeus
25
+ c.configure_faraday do |conn|
26
+ conn.request :url_encoded
27
+ conn.response :logger
28
+ end
29
+ end
30
+ end
31
+
21
32
  def call(exception, options = {})
22
- ensure_eventmachine_running do
33
+ ensure_thread_running do
23
34
  execute_with_rescue do
24
35
  EM::HttpRequest.use AsanaExceptionNotifier::Request::Middleware if ENV['DEBUG_ASANA_EXCEPTION_NOTIFIER']
25
36
  error_page = AsanaExceptionNotifier::ErrorPage.new(template_path, exception, options)
@@ -83,37 +94,24 @@ module ExceptionNotifier
83
94
  #
84
95
  # @return [void]
85
96
  def create_asana_task(error_page)
86
- AsanaExceptionNotifier::Request::Client.new(@default_options.fetch(:asana_api_key, nil),
87
- 'https://app.asana.com/api/1.0/tasks',
88
- 'http_method' => 'post',
89
- 'em_request' => { body: build_request_options(error_page) },
90
- 'action' => 'creation'
91
- ) do |http_response|
92
- ensure_eventmachine_running do
93
- upload_log_file_to_task(error_page, http_response.fetch('data', {}))
94
- end
97
+ task = asana_client.tasks.create(build_request_options(error_page))
98
+ ensure_thread_running do
99
+ upload_log_file_to_task(error_page, task)
95
100
  end
96
101
  end
97
102
 
98
- def upload_log_file_to_task(error_page, task_data)
103
+ def upload_log_file_to_task(error_page, task)
99
104
  archives = error_page.fetch_all_archives
100
105
  archives.each do |zip|
101
- upload_archive(zip, task_data)
106
+ upload_archive(zip, task)
102
107
  end
103
108
  end
104
109
 
105
- def upload_archive(zip, task_data)
106
- return if task_data.blank?
107
- body = multipart_file_upload_details(zip)
108
- AsanaExceptionNotifier::Request::Client.new(@default_options.fetch(:asana_api_key, nil),
109
- "https://app.asana.com/api/1.0/tasks/#{task_data['id']}/attachments",
110
- 'http_method' => 'post',
111
- 'em_request' => body,
112
- 'request_name' => zip,
113
- 'action' => 'upload'
114
- ) do |_http_response|
110
+ def upload_archive(zip, task)
111
+ return if task.blank?
112
+ attachment = task.attach(filename: zip,
113
+ mime: 'application/zip')
115
114
  FileUtils.rm_rf([zip])
116
- end
117
115
  end
118
116
  end
119
117
  end
@@ -77,17 +77,9 @@ module AsanaExceptionNotifier
77
77
  Rails.logger
78
78
  end
79
79
 
80
- def ensure_eventmachine_running(&block)
80
+ def ensure_thread_running(&block)
81
81
  Thread.abort_on_exception = true
82
- register_em_error_handler
83
- run_em_reactor(&block)
84
- end
85
-
86
- def register_em_error_handler
87
- EM.error_handler do |error|
88
- logger.debug '[AsanaExceptionNotifier]: Error during event loop :'
89
- logger.debug "[AsanaExceptionNotifier]: #{log_exception(error)}"
90
- end
82
+ run_new_thread(&block)
91
83
  end
92
84
 
93
85
  def log_exception(exception)
@@ -113,11 +105,9 @@ module AsanaExceptionNotifier
113
105
  puts "\n Command was cancelled due to an Interrupt error."
114
106
  end
115
107
 
116
- def run_em_reactor
108
+ def run_new_thread
117
109
  Thread.new do
118
- EM.run do
119
- EM.defer proc { yield if block_given? }
120
- end
110
+ yield if block_given?
121
111
  end.join
122
112
  end
123
113
 
@@ -202,46 +192,6 @@ module AsanaExceptionNotifier
202
192
  }
203
193
  end
204
194
 
205
- def setup_em_options(options)
206
- options.symbolize_keys!
207
- options[:em_request] ||= {}
208
- options
209
- end
210
-
211
- def create_upload_file_part(file)
212
- Part.new(name: 'file',
213
- body: force_utf8_encoding(File.read(file)),
214
- filename: file,
215
- content_type: 'application/zip'
216
- )
217
- end
218
-
219
- def multipart_file_upload_details(file)
220
- boundary = "---------------------------#{rand(10_000_000_000_000_000_000)}"
221
- body = MultipartBody.new([create_upload_file_part(file)], boundary)
222
- file_upload_request_options(boundary, body, file)
223
- end
224
-
225
- def file_upload_request_options(boundary, body, file)
226
- {
227
- body: body.to_s,
228
- head:
229
- {
230
- 'Content-Type' => "multipart/form-data;boundary=#{boundary}",
231
- 'Content-Length' => File.size(file),
232
- 'Expect' => '100-continue'
233
- }
234
- }
235
- end
236
-
237
- def get_response_from_request(http, _options)
238
- http.respond_to?(:response) ? http.response : http.responses
239
- end
240
-
241
- def get_multi_request_values(http_response, key)
242
- response_method = key.to_s == 'callback' ? 'response' : 'error'
243
- http_response[key.to_sym].values.map { |request| request.send(response_method) }.reject(&:blank?)
244
- end
245
195
 
246
196
  def split_archive(archive, partial_name, segment_size)
247
197
  indexes = Zip::File.split(archive, segment_size, true, partial_name)
@@ -15,9 +15,9 @@ module AsanaExceptionNotifier
15
15
  # major release version
16
16
  MAJOR = 0
17
17
  # minor release version
18
- MINOR = 2
18
+ MINOR = 3
19
19
  # tiny release version
20
- TINY = 2
20
+ TINY = 1
21
21
  # prelease version ( set this only if it is a prelease)
22
22
  PRE = nil
23
23
 
@@ -18,8 +18,9 @@ if defined?(Sidekiq)
18
18
  end
19
19
  require 'exception_notification'
20
20
 
21
- require 'em-http-request'
22
- require 'eventmachine'
21
+ require 'asana'
22
+ require 'typhoeus'
23
+ require 'typhoeus/adapters/faraday'
23
24
 
24
25
  require 'multipart_body'
25
26
  require 'rack'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asana_exception_notifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - bogdanRada
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-05 00:00:00.000000000 Z
11
+ date: 2016-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -31,27 +31,27 @@ dependencies:
31
31
  - !ruby/object:Gem::Version
32
32
  version: '5'
33
33
  - !ruby/object:Gem::Dependency
34
- name: em-http-request
34
+ name: asana
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.1'
39
+ version: '0.5'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 1.1.2
42
+ version: 0.5.0
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: '0.5'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 1.1.2
52
+ version: 0.5.0
53
53
  - !ruby/object:Gem::Dependency
54
- name: eventmachine
54
+ name: typhoeus
55
55
  requirement: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - "~>"
@@ -59,7 +59,7 @@ dependencies:
59
59
  version: '1.0'
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: 1.0.7
62
+ version: 1.0.2
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -69,7 +69,7 @@ dependencies:
69
69
  version: '1.0'
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: 1.0.7
72
+ version: 1.0.2
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: exception_notification
75
75
  requirement: !ruby/object:Gem::Requirement
@@ -428,9 +428,6 @@ files:
428
428
  - lib/asana_exception_notifier/helpers/heredoc_helper.rb
429
429
  - lib/asana_exception_notifier/initializers/hash.rb
430
430
  - lib/asana_exception_notifier/initializers/zip.rb
431
- - lib/asana_exception_notifier/request/client.rb
432
- - lib/asana_exception_notifier/request/core.rb
433
- - lib/asana_exception_notifier/request/middleware.rb
434
431
  - lib/asana_exception_notifier/templates/exception_details.html.erb
435
432
  - lib/asana_exception_notifier/templates/notes.text.erb
436
433
  - lib/asana_exception_notifier/version.rb
@@ -461,7 +458,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
461
458
  version: '2.5'
462
459
  requirements: []
463
460
  rubyforge_project:
464
- rubygems_version: 2.4.8
461
+ rubygems_version: 2.6.4
465
462
  signing_key:
466
463
  specification_version: 4
467
464
  summary: Simple ruby implementation to send notifications to Asana when a exception
@@ -1,85 +0,0 @@
1
- require_relative './core'
2
- module AsanaExceptionNotifier
3
- module Request
4
- # class used to make request in deferrable way
5
- class Client
6
- include AsanaExceptionNotifier::Request::Core
7
- include EM::Deferrable
8
-
9
- attr_reader :url, :options, :api_key, :request_name, :request_final, :action
10
-
11
- def initialize(api_key, url, options, &callback)
12
- @api_key = api_key
13
- @url = url
14
-
15
- @options = options.symbolize_keys
16
- @request_name = @options.fetch(:request_name, '')
17
- @request_final = @options.fetch(:request_final, false)
18
- @action = @options.fetch(:action, '')
19
-
20
- self.callback(&callback)
21
-
22
- send_request_and_rescue
23
- end
24
-
25
- def multi_manager
26
- @multi_manager ||= options.fetch(:multi_manager, nil)
27
- end
28
-
29
- def em_request_options
30
- request = setup_em_options(@options).delete(:em_request)
31
- params = {
32
- head: (request[:head] || {}).merge(
33
- 'Authorization' => "Bearer #{@api_key}"
34
- ),
35
- body: request[:body]
36
- }
37
- super(params)
38
- end
39
-
40
- def send_request_and_rescue
41
- @http = em_request(@url, @options)
42
- send_request
43
- rescue => exception
44
- log_exception(exception)
45
- fail(result: { message: exception })
46
- end
47
-
48
- def send_request
49
- fetch_data(@options) do |http_response|
50
- handle_all_responses(http_response)
51
- end
52
- end
53
-
54
- def handle_all_responses(http_response)
55
- @multi_manager.requests.delete(@http) if @multi_manager.present?
56
- if http_response.is_a?(Hash) && %i(callback errback).all? { |key| http_response.symbolize_keys.keys.include?(key) }
57
- handle_multi_response(http_response)
58
- else
59
- handle_response(http_response, @options.fetch(:request_name, ''))
60
- end
61
- end
62
-
63
- def handle_multi_response(http_response)
64
- logger.debug('[AsanaExceptionNotifier]: Handling multi responses')
65
- get_multi_request_values(http_response, :callback).each { |request_name, response| handle_response(response, request_name) }
66
- get_multi_request_values(http_response, :errback).each { |request_name, response| handle_error(response, request_name) }
67
- end
68
-
69
- def handle_error(error, key = '')
70
- logger.debug("[AsanaExceptionNotifier]: Task #{key} #{@action} returned: #{error}")
71
- fail(error)
72
- end
73
-
74
- def handle_response(http_response, key = '')
75
- logger.debug("[AsanaExceptionNotifier]: Task #{key} #{@action} returned: #{http_response}")
76
- data = JSON.parse(http_response)
77
- callback_task_creation(data)
78
- end
79
-
80
- def callback_task_creation(data)
81
- data.fetch('errors', {}).present? ? handle_error(data) : succeed(data)
82
- end
83
- end
84
- end
85
- end
@@ -1,132 +0,0 @@
1
- require_relative '../helpers/application_helper'
2
- module AsanaExceptionNotifier
3
- module Request
4
- # module that is used for formatting numbers using metrics
5
- #
6
- # @!attribute params
7
- # @return [Hash] THe params received from URL
8
- # @!attribute hostname
9
- # @return [String] THe hostname from where the badges are fetched from
10
- # @!attribute base_url
11
- # @return [String] THe base_url of the API
12
- module Core
13
- include AsanaExceptionNotifier::ApplicationHelper
14
-
15
- # Returns the connection options used for connecting to API's
16
- #
17
- # @return [Hash] Returns the connection options used for connecting to API's
18
- def em_connection_options
19
- {
20
- connect_timeout: 1200, # default connection setup timeout
21
- inactivity_timeout: 120, # default connection inactivity (post-setup) timeout
22
- ssl: {
23
- verify_peer: false
24
- },
25
- head: {
26
- 'ACCEPT' => '*/*',
27
- 'Connection' => 'keep-alive'
28
- }
29
- }
30
- end
31
-
32
- # Returns the request options used for connecting to API's
33
- #
34
- # @return [Hash] Returns the request options used for connecting to API's
35
- def em_request_options(params = {})
36
- {
37
- redirects: 5, # follow 3XX redirects up to depth 5
38
- keepalive: true, # enable keep-alive (don't send Connection:close header)
39
- head: (params[:head] || {}).merge(
40
- 'ACCEPT' => '*/*',
41
- 'Connection' => 'keep-alive'
42
- ),
43
- body: (params[:body] || {})
44
- }
45
- end
46
-
47
- # instantiates an eventmachine http request object that will be used to make the htpp request
48
- # @see EventMachine::HttpRequest#initialize
49
- #
50
- # @param [String] url The URL that will be used in the HTTP request
51
- # @return [EventMachine::HttpRequest] Returns an http request object
52
- def em_request(url, options)
53
- uri = Addressable::URI.parse(url)
54
- conn_options = em_connection_options.merge(ssl: { sni_hostname: uri.host })
55
- em_request = EventMachine::HttpRequest.new(url, conn_options)
56
- em_request.send(options.fetch(:http_method, 'get'), em_request_options)
57
- end
58
-
59
- # Method that fetch the data from a URL and registers the error and success callback to the HTTP object
60
- # @see #em_request
61
- # @see #register_error_callback
62
- # @see #register_success_callback
63
- #
64
- # @param [url] url The URL that is used to fetch data from
65
- # @param [Lambda] callback The callback that will be called if the response is blank
66
- # @param [Proc] block If the response is not blank, the block will receive the response
67
- # @return [void]
68
- def fetch_data(options = {}, &block)
69
- options = options.symbolize_keys
70
- if options[:multi_request] && multi_manager.present?
71
- multi_fetch_data(options, &block)
72
- else
73
- register_error_callback(@http)
74
- register_success_callback(@http, options, &block)
75
- end
76
- end
77
-
78
- def multi_fetch_data(options = {}, &block)
79
- multi_manager.add options[:request_name], @http
80
- return unless options[:request_final]
81
- register_error_callback(multi_manager)
82
- register_success_callback(multi_manager, options, &block)
83
- end
84
-
85
- # Method that is used to register a success callback to a http object
86
- # @see #callback_before_success
87
- # @see #dispatch_http_response
88
- #
89
- # @param [EventMachine::HttpRequest] http The HTTP object that will be used for registering the success callback
90
- # @param [Lambda] callback The callback that will be called if the response is blank
91
- # @param [Proc] block If the response is not blank, the block will receive the response
92
- # @return [void]
93
- def register_success_callback(http, options)
94
- http.callback do
95
- res = callback_before_success(get_response_from_request(http, options))
96
- callback = options.fetch('callback', nil)
97
- block_given? ? yield(res) : callback.call(res)
98
- end
99
- end
100
-
101
- # Callback that is used before returning the response the the instance
102
- #
103
- # @param [String] response The response that will be dispatched to the instance class that made the request
104
- # @return [String] Returns the response
105
- def callback_before_success(response)
106
- response
107
- end
108
-
109
- # This method is used to reqister a error callback to a HTTP request object
110
- # @see #callback_error
111
- # @param [EventMachine::HttpRequest] http The HTTP object that will be used for reqisteringt the error callback
112
- # @return [void]
113
- def register_error_callback(http)
114
- http.errback { |error| callback_error(error) }
115
- end
116
-
117
- def get_error_from_request(http, options)
118
- http_response = http.respond_to?(:response) ? http.response : http.responses[:errback]
119
- options[:multi_request].present? && http_response.is_a?(Hash) ? http_response.values.map(&:response) : http_response
120
- end
121
-
122
- # Method that is used to react when an error happens in a HTTP request
123
- # and prints out an error message
124
- #
125
- # @param [Object] error The error that was raised by the HTTP request
126
- # @return [void]
127
- def callback_error(error)
128
- log_exception(error)
129
- end
130
- end
131
- end
132
- end
@@ -1,41 +0,0 @@
1
- require_relative '../helpers/application_helper'
2
- module AsanaExceptionNotifier
3
- module Request
4
- # middleware used only in development for testing purpose
5
- class Middleware
6
- include AsanaExceptionNotifier::ApplicationHelper
7
- # Method that is used to debug requests to API's
8
- # The method receives the request object and prints it content to console
9
- #
10
- # @param [EventMachine::HttpRequest] client The Http request made to an API
11
- # @param [Hash] head The http headers sent to API
12
- # @param [String, nil] body The body sent to API
13
- # @return [Array<Hash,String>] Returns the http headers and the body
14
- def request(client, head, body)
15
- puts "############## HTTP REQUEST #####################\n"
16
- puts JSON.pretty_generate(
17
- headers: head,
18
- url: client.req.uri,
19
- body: force_utf8_encoding(body.to_s.inspect)
20
- )
21
- [head, body]
22
- end
23
-
24
- # Method that is used to debug responses from API's
25
- # The method receives the response object and prints it content to console
26
- #
27
- # @param [EventMachine::HttpResponse] resp The Http response received from API
28
- # @return [EventMachine::HttpResponse]
29
- def response(resp)
30
- puts "############## HTTP RESPONSE #####################\n"
31
- headers = resp.response_header
32
- puts JSON.pretty_generate(
33
- headers: headers,
34
- status: headers.status,
35
- body: force_utf8_encoding(resp.response.to_s.inspect)
36
- )
37
- resp
38
- end
39
- end
40
- end
41
- end