application_insights 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +9 -9
  2. data/LICENSE.txt +7 -18
  3. data/README.md +42 -7
  4. data/Rakefile +6 -1
  5. data/application_insights.gemspec +2 -0
  6. data/lib/application_insights.rb +1 -0
  7. data/lib/application_insights/channel/asynchronous_queue.rb +51 -0
  8. data/lib/application_insights/channel/asynchronous_sender.rb +121 -0
  9. data/lib/application_insights/channel/contracts/application.rb +3 -2
  10. data/lib/application_insights/channel/contracts/data.rb +3 -2
  11. data/lib/application_insights/channel/contracts/data_point.rb +15 -10
  12. data/lib/application_insights/channel/contracts/device.rb +42 -28
  13. data/lib/application_insights/channel/contracts/envelope.rb +39 -27
  14. data/lib/application_insights/channel/contracts/event_data.rb +6 -6
  15. data/lib/application_insights/channel/contracts/exception_data.rb +9 -8
  16. data/lib/application_insights/channel/contracts/exception_details.rb +15 -11
  17. data/lib/application_insights/channel/contracts/internal.rb +6 -4
  18. data/lib/application_insights/channel/contracts/location.rb +3 -2
  19. data/lib/application_insights/channel/contracts/message_data.rb +6 -5
  20. data/lib/application_insights/channel/contracts/metric_data.rb +3 -3
  21. data/lib/application_insights/channel/contracts/operation.rb +12 -8
  22. data/lib/application_insights/channel/contracts/page_view_data.rb +12 -10
  23. data/lib/application_insights/channel/contracts/remote_dependency_data.rb +27 -19
  24. data/lib/application_insights/channel/contracts/request_data.rb +15 -12
  25. data/lib/application_insights/channel/contracts/session.rb +9 -6
  26. data/lib/application_insights/channel/contracts/stack_frame.rb +9 -6
  27. data/lib/application_insights/channel/contracts/user.rb +12 -8
  28. data/lib/application_insights/channel/event.rb +64 -0
  29. data/lib/application_insights/channel/queue_base.rb +24 -10
  30. data/lib/application_insights/channel/sender_base.rb +38 -9
  31. data/lib/application_insights/channel/synchronous_queue.rb +16 -5
  32. data/lib/application_insights/channel/synchronous_sender.rb +4 -2
  33. data/lib/application_insights/channel/telemetry_channel.rb +26 -7
  34. data/lib/application_insights/channel/telemetry_context.rb +29 -10
  35. data/lib/application_insights/telemetry_client.rb +84 -15
  36. data/lib/application_insights/unhandled_exception.rb +48 -0
  37. data/lib/application_insights/version.rb +1 -1
  38. data/test/application_insights/channel/test_asynchronous_queue.rb +68 -0
  39. data/test/application_insights/channel/test_asynchronous_sender.rb +81 -0
  40. data/test/application_insights/channel/test_event.rb +53 -0
  41. data/test/application_insights/channel/test_queue_base.rb +10 -9
  42. data/test/application_insights/channel/test_sender_base.rb +0 -9
  43. data/test/application_insights/test_telemetry_client.rb +5 -0
  44. data/test/application_insights/test_unhandled_exception.rb +42 -0
  45. metadata +44 -3
@@ -0,0 +1,48 @@
1
+ require_relative 'telemetry_client'
2
+ require_relative 'channel/telemetry_channel'
3
+ require_relative 'channel/synchronous_queue'
4
+ require_relative 'channel/synchronous_sender'
5
+
6
+ include ApplicationInsights
7
+
8
+ module ApplicationInsights
9
+ module UnhandledException
10
+ @sender = nil
11
+
12
+ # Auto collects unhandled exception and send to the Application Insights service.
13
+ # @param (string) instrumentation_key used to identify which Application Insights application this data is for.
14
+ # @example
15
+ # require 'application_insights'
16
+ # ApplicationInsights::UnhandledException.collect('<YOUR INSTRUMENTATION KEY GOES HERE>')
17
+ # raise Exception, 'Boom!'
18
+ def self.collect(instrumentation_key)
19
+ at_exit do
20
+ # Avoid sending exception more than once if this method got invoked multiple times
21
+ send(instrumentation_key) if !@sender
22
+ end
23
+ end
24
+
25
+ # @api private
26
+ # Send the last raised exception to the Application Insights service if telemetry_sender is not customized.
27
+ # @param (string) instrumentation_key used to identify which Application Insights application this data is for.
28
+ # @param (SenderBase) telemetry_sender used to send the last raised exception.
29
+ def self.send(instrumentation_key, telemetry_sender = nil)
30
+ if $! && !$!.is_a?(SystemExit) && !$!.is_a?(SignalException)
31
+ if telemetry_sender
32
+ @sender = telemetry_sender
33
+ elsif !@sender
34
+ # Use a synchronized sender to guarantee the data would be sent out once flush
35
+ @sender = Channel::SynchronousSender.new
36
+ end
37
+
38
+ queue = Channel::SynchronousQueue.new @sender
39
+ channel = Channel::TelemetryChannel.new nil, queue
40
+ client = TelemetryClient.new channel
41
+ client.context.instrumentation_key = instrumentation_key
42
+ client.track_exception($!, {:handled_at => 'Unhandled'})
43
+ client.flush
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -1,3 +1,3 @@
1
1
  module ApplicationInsights
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -0,0 +1,68 @@
1
+ require_relative '../../../lib/application_insights/channel/sender_base'
2
+ require_relative '../../../lib/application_insights/channel/asynchronous_queue'
3
+ require 'test/unit'
4
+
5
+ include ApplicationInsights::Channel
6
+
7
+ class TestAsynchronousQueue < Test::Unit::TestCase
8
+ def test_initialize
9
+ queue = AsynchronousQueue.new MockAsynchronousSender.new
10
+ assert_not_nil queue.flush_notification
11
+ end
12
+
13
+ def test_flush_notification_works_as_expected
14
+ queue = AsynchronousQueue.new MockAsynchronousSender.new
15
+ assert_not_nil queue.flush_notification
16
+ result = queue.flush_notification.wait 1
17
+ assert_equal false, result
18
+ queue.flush_notification.set
19
+ result = queue.flush_notification.wait
20
+ assert_equal true, result
21
+ queue.flush_notification.clear
22
+ result = queue.flush_notification.wait 1
23
+ assert_equal false, result
24
+ end
25
+
26
+ def test_push_works_As_expected
27
+ sender = MockAsynchronousSender.new
28
+ queue = AsynchronousQueue.new sender
29
+ queue.push 42
30
+ assert_equal 1, sender.start_call_count
31
+ assert_equal 42, queue.pop
32
+ assert_nil queue.pop
33
+ end
34
+
35
+ def test_flush_works_as_expected
36
+ sender = MockAsynchronousSender.new
37
+ queue = AsynchronousQueue.new sender
38
+ assert_not_nil queue.flush_notification
39
+ result = queue.flush_notification.wait 1
40
+ assert_equal false, result
41
+ queue.flush
42
+ assert_equal 1, sender.start_call_count
43
+ result = queue.flush_notification.wait
44
+ assert_equal true, result
45
+ end
46
+ end
47
+
48
+ class MockAsynchronousSender
49
+ def initialize
50
+ @send_buffer_size = 2
51
+ @data = []
52
+ @queue = nil
53
+ @start_call_count = 0
54
+ end
55
+
56
+ attr_accessor :start_call_count
57
+ attr_accessor :send_buffer_size
58
+ attr_accessor :data
59
+ attr_accessor :queue
60
+
61
+ def start
62
+ @start_call_count += 1
63
+ end
64
+
65
+ def send(data_to_send)
66
+ @data.push data_to_send
67
+ end
68
+ end
@@ -0,0 +1,81 @@
1
+ require_relative '../../../lib/application_insights/channel/sender_base'
2
+ require_relative '../../../lib/application_insights/channel/asynchronous_sender'
3
+ require_relative '../../../lib/application_insights/channel/asynchronous_queue'
4
+ require 'test/unit'
5
+
6
+ include ApplicationInsights::Channel
7
+
8
+ class TestAsynchronousSender < Test::Unit::TestCase
9
+ def test_initialize
10
+ sender = AsynchronousSender.new
11
+ assert_equal 'https://dc.services.visualstudio.com/v2/track', sender.service_endpoint_uri
12
+ assert_equal 1.0, sender.send_interval
13
+ assert_equal 3.0, sender.send_time
14
+ end
15
+
16
+ def test_send_interval_works_as_expected
17
+ sender = AsynchronousSender.new
18
+ assert_equal 1.0, sender.send_interval
19
+ sender.send_interval = 10.0
20
+ assert_equal 10.0, sender.send_interval
21
+ end
22
+
23
+ def test_send_time_works_as_expected
24
+ sender = AsynchronousSender.new
25
+ assert_equal 3.0, sender.send_time
26
+ sender.send_time = 10.0
27
+ assert_equal 10.0, sender.send_time
28
+ end
29
+
30
+ def test_work_thread_works_as_expected
31
+ sender = InterceptableAsynchronousSender.new
32
+ assert_nil sender.work_thread
33
+ sender.send_interval = 1.0
34
+ sender.send_time = 3.0
35
+ queue = AsynchronousQueue.new sender
36
+ sender.invoke_base_start = true
37
+ queue.push 1
38
+ assert_not_nil sender.work_thread
39
+ sleep 3.0
40
+ assert_nil sender.work_thread
41
+ end
42
+
43
+ def test_start
44
+ sender = InterceptableAsynchronousSender.new
45
+ sender.send_interval = 1.0
46
+ sender.send_time = 3.0
47
+ queue = AsynchronousQueue.new sender
48
+ sender.invoke_base_start = false
49
+ queue.push 1
50
+ queue.push 2
51
+ sender.invoke_base_start = true
52
+ sender.start
53
+ sleep 2.0
54
+ queue.push 3
55
+ sleep 5.0
56
+ data = sender.data_to_send
57
+ assert_equal [[1, 2], [3]], data
58
+ end
59
+
60
+ end
61
+
62
+ class InterceptableAsynchronousSender < AsynchronousSender
63
+ def initialize
64
+ @data_to_send = []
65
+ @invoke_base_start = false
66
+ super
67
+ end
68
+
69
+ attr_accessor :invoke_base_start
70
+ attr_accessor :data_to_send
71
+
72
+ def start
73
+ if invoke_base_start
74
+ super
75
+ end
76
+ end
77
+
78
+ def send(data_to_send)
79
+ @data_to_send.push data_to_send
80
+ end
81
+ end
@@ -0,0 +1,53 @@
1
+ require_relative '../../../lib/application_insights/channel/sender_base'
2
+ require_relative '../../../lib/application_insights/channel/asynchronous_queue'
3
+ require 'thread'
4
+ require 'test/unit'
5
+
6
+ include ApplicationInsights::Channel
7
+
8
+ class TestEvent < Test::Unit::TestCase
9
+ def test_initialize
10
+ event = Event.new
11
+ assert_equal false, event.signal
12
+ end
13
+
14
+ def test_set_works_as_expected
15
+ event = Event.new
16
+ assert_equal false, event.signal
17
+ Thread.new do
18
+ sleep 1
19
+ event.set
20
+ end
21
+ result = event.wait 2.0
22
+ assert_equal true, result
23
+ end
24
+
25
+ def test_clear_works_as_expected
26
+ event = Event.new
27
+ assert_equal false, event.signal
28
+ event.set
29
+ assert_equal true, event.signal
30
+ event.clear
31
+ assert_equal false, event.signal
32
+ end
33
+
34
+ def test_wait_works_as_expected
35
+ event1 = Event.new
36
+ assert_equal false, event1.signal
37
+ Thread.new do
38
+ sleep 1
39
+ event1.set
40
+ end
41
+ result = event1.wait 0.5
42
+ assert_equal false, result
43
+
44
+ event2 = Event.new
45
+ assert_equal false, event1.signal
46
+ Thread.new do
47
+ sleep 1
48
+ event2.set
49
+ end
50
+ result = event2.wait 2.0
51
+ assert_equal true, result
52
+ end
53
+ end
@@ -5,15 +5,6 @@ require 'test/unit'
5
5
  include ApplicationInsights::Channel
6
6
 
7
7
  class TestQueueBase < Test::Unit::TestCase
8
- def test_initialize_raises_exception_when_sender_is_nil
9
- begin
10
- QueueBase.new nil
11
- assert false
12
- rescue ArgumentError => e
13
- assert_equal 'Sender was required but not provided', e.message
14
- end
15
- end
16
-
17
8
  def test_initialize
18
9
  sender = SenderBase.new 'http://tempuri.org'
19
10
  item = QueueBase.new sender
@@ -72,6 +63,16 @@ class TestQueueBase < Test::Unit::TestCase
72
63
  assert_equal i, item.pop
73
64
  end
74
65
  end
66
+
67
+ def test_empty_works_as_expected
68
+ sender = SenderBase.new 'http://tempuri.org'
69
+ queue = QueueBase.new sender
70
+ assert_equal true, queue.empty?
71
+ queue.push 1
72
+ assert_equal false, queue.empty?
73
+ queue.pop
74
+ assert_equal true, queue.empty?
75
+ end
75
76
  end
76
77
 
77
78
  class MockQueueBase < QueueBase
@@ -7,15 +7,6 @@ require 'thread'
7
7
  include ApplicationInsights::Channel
8
8
 
9
9
  class TestSenderBase < Test::Unit::TestCase
10
- def test_initialize_raises_exception_when_service_endpoint_uri_is_nil
11
- begin
12
- SenderBase.new nil
13
- assert false
14
- rescue ArgumentError => e
15
- assert_equal 'Service endpoint URI was required but not provided', e.message
16
- end
17
- end
18
-
19
10
  def test_initialize
20
11
  sender = SenderBase.new 'http://tempuri.org'
21
12
  assert_equal 'http://tempuri.org', sender.service_endpoint_uri
@@ -48,8 +48,13 @@ class TestTelemetryClient < Test::Unit::TestCase
48
48
  end
49
49
  client.flush
50
50
  expected = '[{"ver":1,"name":"Microsoft.ApplicationInsights.Exception","time":"TIME_PLACEHOLDER","sampleRate":100.0,"tags":{"ai.internal.sdkVersion":"rb:0.1.0"},"data":{"baseType":"ExceptionData","baseData":{"ver":2,"handledAt":"UserCode","exceptions":[{"id":1,"outerId":0,"typeName":"ArgumentError","message":"Some error","hasFullStack":true,"stack":"STACK_PLACEHOLDER"}]}}}]'
51
+ assert_equal 'UserCode', sender.data_to_send[0].data.base_data.handled_at
52
+ assert_operator sender.data_to_send[0].data.base_data.exceptions[0].parsed_stack.count, :>, 0
53
+ assert_equal 'test_track_exception_works_as_expected', sender.data_to_send[0].data.base_data.exceptions[0].parsed_stack[0].method
54
+ assert_equal __FILE__, sender.data_to_send[0].data.base_data.exceptions[0].parsed_stack[0].file_name
51
55
  sender.data_to_send[0].time = 'TIME_PLACEHOLDER'
52
56
  sender.data_to_send[0].data.base_data.exceptions[0].stack = 'STACK_PLACEHOLDER'
57
+ sender.data_to_send[0].data.base_data.exceptions[0].parsed_stack = []
53
58
  actual = sender.data_to_send.to_json
54
59
  assert_equal expected, actual
55
60
  end
@@ -0,0 +1,42 @@
1
+ require 'test/unit'
2
+ require_relative '../../lib/application_insights/unhandled_exception'
3
+
4
+ include ApplicationInsights
5
+
6
+ class TestUnhandledException < Test::Unit::TestCase
7
+
8
+ def test_send
9
+ sender = MockSender.new
10
+ error = 'Boom!'
11
+ instrumentation_key = 'one'
12
+ begin
13
+ raise StandardError, error
14
+ rescue
15
+ UnhandledException.send instrumentation_key, sender
16
+ end
17
+
18
+ assert_equal 1, sender.buffer.count
19
+ payload = sender.buffer[0]
20
+ assert_equal instrumentation_key, payload[0].i_key
21
+ assert_equal 'Unhandled', payload[0].data.base_data.handled_at
22
+ end
23
+ end
24
+
25
+ class MockSender
26
+ def initialize
27
+ @buffer = []
28
+ @queue = nil
29
+ @send_buffer_size = 100
30
+ end
31
+
32
+ attr_accessor :buffer
33
+ attr_accessor :queue
34
+ attr_accessor :send_buffer_size
35
+
36
+ def send(data)
37
+ @buffer << data
38
+ end
39
+
40
+ def flush
41
+ end
42
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: application_insights
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Microsoft
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-17 00:00:00.000000000 Z
11
+ date: 2015-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.7.6
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.7.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: redcarpet
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 3.2.2
41
69
  description: This project extends the Application Insights API surface to support
42
70
  Ruby.
43
71
  email:
@@ -53,6 +81,8 @@ files:
53
81
  - Rakefile
54
82
  - application_insights.gemspec
55
83
  - lib/application_insights.rb
84
+ - lib/application_insights/channel/asynchronous_queue.rb
85
+ - lib/application_insights/channel/asynchronous_sender.rb
56
86
  - lib/application_insights/channel/contracts/application.rb
57
87
  - lib/application_insights/channel/contracts/data.rb
58
88
  - lib/application_insights/channel/contracts/data_point.rb
@@ -77,6 +107,7 @@ files:
77
107
  - lib/application_insights/channel/contracts/severity_level.rb
78
108
  - lib/application_insights/channel/contracts/stack_frame.rb
79
109
  - lib/application_insights/channel/contracts/user.rb
110
+ - lib/application_insights/channel/event.rb
80
111
  - lib/application_insights/channel/queue_base.rb
81
112
  - lib/application_insights/channel/sender_base.rb
82
113
  - lib/application_insights/channel/synchronous_queue.rb
@@ -84,6 +115,7 @@ files:
84
115
  - lib/application_insights/channel/telemetry_channel.rb
85
116
  - lib/application_insights/channel/telemetry_context.rb
86
117
  - lib/application_insights/telemetry_client.rb
118
+ - lib/application_insights/unhandled_exception.rb
87
119
  - lib/application_insights/version.rb
88
120
  - test/application_insights.rb
89
121
  - test/application_insights/channel/contracts/test_application.rb
@@ -105,6 +137,9 @@ files:
105
137
  - test/application_insights/channel/contracts/test_session.rb
106
138
  - test/application_insights/channel/contracts/test_stack_frame.rb
107
139
  - test/application_insights/channel/contracts/test_user.rb
140
+ - test/application_insights/channel/test_asynchronous_queue.rb
141
+ - test/application_insights/channel/test_asynchronous_sender.rb
142
+ - test/application_insights/channel/test_event.rb
108
143
  - test/application_insights/channel/test_queue_base.rb
109
144
  - test/application_insights/channel/test_sender_base.rb
110
145
  - test/application_insights/channel/test_synchronous_queue.rb
@@ -112,6 +147,7 @@ files:
112
147
  - test/application_insights/channel/test_telemetry_channel.rb
113
148
  - test/application_insights/channel/test_telemetry_context.rb
114
149
  - test/application_insights/test_telemetry_client.rb
150
+ - test/application_insights/test_unhandled_exception.rb
115
151
  homepage: https://github.com/Microsoft/AppInsights-Ruby
116
152
  licenses:
117
153
  - MIT
@@ -132,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
168
  version: '0'
133
169
  requirements: []
134
170
  rubyforge_project:
135
- rubygems_version: 2.4.5
171
+ rubygems_version: 2.0.3
136
172
  signing_key:
137
173
  specification_version: 4
138
174
  summary: Application Insights SDK for Ruby
@@ -157,6 +193,9 @@ test_files:
157
193
  - test/application_insights/channel/contracts/test_session.rb
158
194
  - test/application_insights/channel/contracts/test_stack_frame.rb
159
195
  - test/application_insights/channel/contracts/test_user.rb
196
+ - test/application_insights/channel/test_asynchronous_queue.rb
197
+ - test/application_insights/channel/test_asynchronous_sender.rb
198
+ - test/application_insights/channel/test_event.rb
160
199
  - test/application_insights/channel/test_queue_base.rb
161
200
  - test/application_insights/channel/test_sender_base.rb
162
201
  - test/application_insights/channel/test_synchronous_queue.rb
@@ -164,3 +203,5 @@ test_files:
164
203
  - test/application_insights/channel/test_telemetry_channel.rb
165
204
  - test/application_insights/channel/test_telemetry_context.rb
166
205
  - test/application_insights/test_telemetry_client.rb
206
+ - test/application_insights/test_unhandled_exception.rb
207
+ has_rdoc: