asana_exception_notifier 0.2.2 → 0.3.1

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
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