application_insights 0.5.3 → 0.5.4

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 (82) hide show
  1. checksums.yaml +6 -14
  2. data/.travis.yml +21 -9
  3. data/CONTRIBUTING.md +30 -0
  4. data/Gemfile +4 -4
  5. data/LICENSE.txt +11 -11
  6. data/README.md +13 -14
  7. data/Rakefile +14 -14
  8. data/application_insights.gemspec +28 -29
  9. data/lib/application_insights.rb +9 -9
  10. data/lib/application_insights/channel/asynchronous_queue.rb +58 -51
  11. data/lib/application_insights/channel/asynchronous_sender.rb +132 -123
  12. data/lib/application_insights/channel/contracts/application.rb +14 -53
  13. data/lib/application_insights/channel/contracts/cloud.rb +14 -0
  14. data/lib/application_insights/channel/contracts/data.rb +14 -48
  15. data/lib/application_insights/channel/contracts/data_point.rb +24 -130
  16. data/lib/application_insights/channel/contracts/data_point_type.rb +7 -16
  17. data/lib/application_insights/channel/contracts/dependency_kind.rb +9 -19
  18. data/lib/application_insights/channel/contracts/dependency_source_type.rb +9 -19
  19. data/lib/application_insights/channel/contracts/device.rb +28 -257
  20. data/lib/application_insights/channel/contracts/envelope.rb +40 -266
  21. data/lib/application_insights/channel/contracts/event_data.rb +28 -77
  22. data/lib/application_insights/channel/contracts/exception_data.rb +37 -140
  23. data/lib/application_insights/channel/contracts/exception_details.rb +28 -129
  24. data/lib/application_insights/channel/contracts/internal.rb +14 -53
  25. data/lib/application_insights/channel/contracts/json_serializable.rb +59 -59
  26. data/lib/application_insights/channel/contracts/location.rb +16 -36
  27. data/lib/application_insights/channel/contracts/message_data.rb +24 -77
  28. data/lib/application_insights/channel/contracts/metric_data.rb +27 -60
  29. data/lib/application_insights/channel/contracts/operation.rb +19 -121
  30. data/lib/application_insights/channel/contracts/page_view_data.rb +30 -111
  31. data/lib/application_insights/channel/contracts/remote_dependency_data.rb +56 -260
  32. data/lib/application_insights/channel/contracts/request_data.rb +36 -176
  33. data/lib/application_insights/channel/contracts/session.rb +15 -70
  34. data/lib/application_insights/channel/contracts/severity_level.rb +13 -25
  35. data/lib/application_insights/channel/contracts/stack_frame.rb +17 -94
  36. data/lib/application_insights/channel/contracts/user.rb +19 -104
  37. data/lib/application_insights/channel/event.rb +68 -64
  38. data/lib/application_insights/channel/queue_base.rb +65 -62
  39. data/lib/application_insights/channel/sender_base.rb +79 -72
  40. data/lib/application_insights/channel/synchronous_queue.rb +45 -39
  41. data/lib/application_insights/channel/synchronous_sender.rb +17 -15
  42. data/lib/application_insights/channel/telemetry_channel.rb +120 -102
  43. data/lib/application_insights/channel/telemetry_context.rb +85 -68
  44. data/lib/application_insights/rack/track_request.rb +87 -84
  45. data/lib/application_insights/telemetry_client.rb +229 -217
  46. data/lib/application_insights/unhandled_exception.rb +49 -47
  47. data/lib/application_insights/version.rb +3 -3
  48. data/test/application_insights.rb +8 -9
  49. data/test/application_insights/channel/contracts/test_application.rb +44 -44
  50. data/test/application_insights/channel/contracts/test_cloud.rb +44 -0
  51. data/test/application_insights/channel/contracts/test_data.rb +44 -44
  52. data/test/application_insights/channel/contracts/test_data_point.rb +109 -109
  53. data/test/application_insights/channel/contracts/test_device.rb +200 -200
  54. data/test/application_insights/channel/contracts/test_envelope.rb +209 -209
  55. data/test/application_insights/channel/contracts/test_event_data.rb +62 -62
  56. data/test/application_insights/channel/contracts/test_exception_data.rb +111 -111
  57. data/test/application_insights/channel/contracts/test_exception_details.rb +106 -106
  58. data/test/application_insights/channel/contracts/test_internal.rb +44 -44
  59. data/test/application_insights/channel/contracts/test_location.rb +70 -31
  60. data/test/application_insights/channel/contracts/test_message_data.rb +66 -66
  61. data/test/application_insights/channel/contracts/test_metric_data.rb +50 -50
  62. data/test/application_insights/channel/contracts/test_operation.rb +109 -96
  63. data/test/application_insights/channel/contracts/test_page_view_data.rb +88 -88
  64. data/test/application_insights/channel/contracts/test_remote_dependency_data.rb +209 -209
  65. data/test/application_insights/channel/contracts/test_request_data.rb +153 -153
  66. data/test/application_insights/channel/contracts/test_session.rb +57 -57
  67. data/test/application_insights/channel/contracts/test_stack_frame.rb +83 -83
  68. data/test/application_insights/channel/contracts/test_user.rb +96 -83
  69. data/test/application_insights/channel/test_asynchronous_queue.rb +47 -47
  70. data/test/application_insights/channel/test_asynchronous_sender.rb +80 -80
  71. data/test/application_insights/channel/test_event.rb +52 -52
  72. data/test/application_insights/channel/test_queue_base.rb +88 -88
  73. data/test/application_insights/channel/test_sender_base.rb +87 -87
  74. data/test/application_insights/channel/test_synchronous_queue.rb +27 -27
  75. data/test/application_insights/channel/test_synchronous_sender.rb +10 -10
  76. data/test/application_insights/channel/test_telemetry_channel.rb +126 -102
  77. data/test/application_insights/channel/test_telemetry_context.rb +82 -74
  78. data/test/application_insights/mock_sender.rb +37 -37
  79. data/test/application_insights/rack/test_track_request.rb +142 -139
  80. data/test/application_insights/test_telemetry_client.rb +133 -123
  81. data/test/application_insights/test_unhandled_exception.rb +23 -24
  82. metadata +23 -33
@@ -1,64 +1,68 @@
1
- require_relative 'queue_base'
2
- require 'thread'
3
-
4
- module ApplicationInsights
5
- module Channel
6
- # An event class that allows simple cross-thread signalling.
7
- #
8
- # An object of this type managers an internal flag that can be set to true via the {#set} method and reset via the
9
- # {#clear} method. Calling the {#wait} method will block until the flag is set to true.
10
- # @example
11
- # require 'application_insights'
12
- # require 'thread'
13
- # event = ApplicationInsights::Channel::Event.new
14
- # Thread.new do
15
- # sleep 1
16
- # event.set
17
- # end
18
- # puts 'Main screen turn on.'
19
- # result = event.wait
20
- # puts 'All your base are belong to us.'
21
- class Event
22
- # Initializes a new instance of the class.
23
- def initialize
24
- @mutex = Mutex.new
25
- @condition_variable = ConditionVariable.new
26
- @signal = false
27
- end
28
-
29
- # The signal value for this object. Note that the value of this property is not synchronized
30
- # with respect to {#set} and {#clear} meaning that it could return false positives or negatives.
31
- # @return [Boolean] the signal value.
32
- attr_reader :signal
33
-
34
- # Sets the internal flag to true. Calling this method will also cause all waiting threads to awaken.
35
- def set
36
- @mutex.synchronize do
37
- @signal = true
38
- @condition_variable.broadcast
39
- end
40
- end
41
-
42
- # Sets the internal flag to false.
43
- def clear
44
- @mutex.synchronize do
45
- @signal = false
46
- end
47
- end
48
-
49
- # Calling this method will block until the internal flag is set to true. If the flag is set to true before calling
50
- # this method, we will return immediately. If the timeout parameter is specified, the method will unblock after the
51
- # specified number of seconds.
52
- # @param [Fixnum] timeout the timeout for the operation in seconds.
53
- # @return [Boolean] the value of the internal flag on exit.
54
- def wait(timeout=nil)
55
- @mutex.synchronize do
56
- if @signal == false
57
- @condition_variable.wait @mutex, (timeout == nil) ? nil : timeout
58
- end
59
- @signal
60
- end
61
- end
62
- end
63
- end
64
- end
1
+ require_relative 'queue_base'
2
+ require 'thread'
3
+
4
+ module ApplicationInsights
5
+ module Channel
6
+ # An event class that allows simple cross-thread signalling.
7
+ #
8
+ # An object of this type managers an internal flag that can be set to true
9
+ # via the {#set} method and reset via the {#clear} method. Calling the
10
+ # {#wait} method will block until the flag is set to true.
11
+ #
12
+ # @example
13
+ # require 'application_insights'
14
+ # require 'thread'
15
+ # event = ApplicationInsights::Channel::Event.new
16
+ # Thread.new do
17
+ # sleep 1
18
+ # event.set
19
+ # end
20
+ # puts 'Main screen turn on.'
21
+ # result = event.wait
22
+ # puts 'All your base are belong to us.'
23
+ class Event
24
+ # Initializes a new instance of the class.
25
+ def initialize
26
+ @mutex = Mutex.new
27
+ @condition_variable = ConditionVariable.new
28
+ @signal = false
29
+ end
30
+
31
+ # The signal value for this object. Note that the value of this property is
32
+ # not synchronized with respect to {#set} and {#clear} meaning that it
33
+ # could return false positives or negatives.
34
+ # @return [Boolean] the signal value.
35
+ attr_reader :signal
36
+
37
+ # Sets the internal flag to true. Calling this method will also cause all
38
+ # waiting threads to awaken.
39
+ def set
40
+ @mutex.synchronize do
41
+ @signal = true
42
+ @condition_variable.broadcast
43
+ end
44
+ end
45
+
46
+ # Sets the internal flag to false.
47
+ def clear
48
+ @mutex.synchronize do
49
+ @signal = false
50
+ end
51
+ end
52
+
53
+ # Calling this method will block until the internal flag is set to true.
54
+ # If the flag is set to true before calling this method, we will return
55
+ # immediately. If the timeout parameter is specified, the method will
56
+ # unblock after the specified number of seconds.
57
+ # @param [Fixnum] timeout the timeout for the operation in seconds.
58
+ # @return [Boolean] the value of the internal flag on exit.
59
+ def wait(timeout=nil)
60
+ @mutex.synchronize do
61
+ @condition_variable.wait(@mutex, timeout) unless @signal
62
+ end
63
+
64
+ @signal
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,62 +1,65 @@
1
- require 'thread'
2
-
3
- module ApplicationInsights
4
- module Channel
5
- # The base class for all types of queues for use in conjunction with an implementation of {SenderBase}. The queue
6
- # will notify the sender that it needs to pick up items when it reaches {#max_queue_length}, or when the consumer
7
- # calls {#flush}.
8
- class QueueBase
9
- # Initializes a new instance of the class.
10
- # @param [SenderBase] sender the sender object that will be used in conjunction with this queue.
11
- def initialize(sender)
12
- @queue = Queue.new
13
- @max_queue_length = 500
14
- @sender = sender
15
- @sender.queue = self if sender
16
- end
17
-
18
- # The maximum number of items that will be held by the queue before the queue will call the {#flush} method.
19
- # @return [Fixnum] the maximum queue size. (defaults to: 500)
20
- attr_accessor :max_queue_length
21
-
22
- # The sender that is associated with this queue that this queue will use to send data to the service.
23
- # @return [SenderBase] the sender object.
24
- attr_reader :sender
25
-
26
- # Adds the passed in item object to the queue and calls {#flush} if the size of the queue is larger
27
- # than {#max_queue_length}. This method does nothing if the passed in item is nil.
28
- # @param [Contracts::Envelope] item the telemetry envelope object to send to the service.
29
- def push(item)
30
- unless item
31
- return
32
- end
33
-
34
- @queue.push(item)
35
- if @queue.length >= @max_queue_length
36
- flush
37
- end
38
- end
39
-
40
- # Pops a single item from the queue and returns it. If the queue is empty, this method will return nil.
41
- # @return [Contracts::Envelope] a telemetry envelope object or nil if the queue is empty.
42
- def pop
43
- begin
44
- return @queue.pop(TRUE)
45
- rescue ThreadError => _
46
- return nil
47
- end
48
- end
49
-
50
- # Flushes the current queue by notifying the {#sender}. This method needs to be overridden by a concrete
51
- # implementations of the queue class.
52
- def flush
53
- end
54
-
55
- # Indicates whether the queue is empty.
56
- # @return [Boolean] true if the queue is empty
57
- def empty?
58
- @queue.empty?
59
- end
60
- end
61
- end
62
- end
1
+ require 'thread'
2
+
3
+ module ApplicationInsights
4
+ module Channel
5
+ # The base class for all types of queues for use in conjunction with an
6
+ # implementation of {SenderBase}. The queue will notify the sender that it
7
+ # needs to pick up items when it reaches {#max_queue_length}, or when the
8
+ # consumer calls {#flush}.
9
+ class QueueBase
10
+ # Initializes a new instance of the class.
11
+ # @param [SenderBase] sender the sender object that will be used in
12
+ # conjunction with this queue.
13
+ def initialize(sender)
14
+ @queue = Queue.new
15
+ @max_queue_length = 500
16
+ @sender = sender
17
+ @sender.queue = self if sender
18
+ end
19
+
20
+ # The maximum number of items that will be held by the queue before the
21
+ # queue will call the {#flush} method.
22
+ # @return [Fixnum] the maximum queue size. (defaults to: 500)
23
+ attr_accessor :max_queue_length
24
+
25
+ # The sender that is associated with this queue that this queue will use to
26
+ # send data to the service.
27
+ # @return [SenderBase] the sender object.
28
+ attr_reader :sender
29
+
30
+ # Adds the passed in item object to the queue and calls {#flush} if the
31
+ # size of the queue is larger than {#max_queue_length}. This method does
32
+ # nothing if the passed in item is nil.
33
+ # @param [Contracts::Envelope] item the telemetry envelope object to send
34
+ # to the service.
35
+ def push(item)
36
+ return unless item
37
+
38
+ @queue.push(item)
39
+
40
+ flush if @queue.length >= @max_queue_length
41
+ end
42
+
43
+ # Pops a single item from the queue and returns it. If the queue is empty,
44
+ # this method will return nil.
45
+ # @return [Contracts::Envelope] a telemetry envelope object or nil if the
46
+ # queue is empty.
47
+ def pop
48
+ return @queue.pop(true)
49
+ rescue ThreadError
50
+ return nil
51
+ end
52
+
53
+ # Flushes the current queue by notifying the {#sender}. This method needs
54
+ # to be overridden by a concrete implementations of the queue class.
55
+ def flush
56
+ end
57
+
58
+ # Indicates whether the queue is empty.
59
+ # @return [Boolean] true if the queue is empty
60
+ def empty?
61
+ @queue.empty?
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,72 +1,79 @@
1
- require 'json'
2
- require 'net/http'
3
- require 'openssl'
4
- require 'stringio'
5
- require 'zlib'
6
-
7
- module ApplicationInsights
8
- module Channel
9
- # The base class for all types of senders for use in conjunction with an implementation of {QueueBase}. The queue
10
- # will notify the sender that it needs to pick up items. The concrete sender implementation will listen to these
11
- # notifications and will pull items from the queue using {QueueBase#pop} getting at most {#send_buffer_size} items.
12
- # It will then call {#send} using the list of items pulled from the queue.
13
- class SenderBase
14
- # Initializes a new instance of the class.
15
- # @param [String] service_endpoint_uri the address of the service to send telemetry data to.
16
- def initialize(service_endpoint_uri)
17
- @service_endpoint_uri = service_endpoint_uri
18
- @queue = nil
19
- @send_buffer_size = 100
20
- end
21
-
22
- # The service endpoint URI where this sender will send data to.
23
- # @return [String] the service endpoint URI.
24
- attr_accessor :service_endpoint_uri
25
-
26
- # The queue that this sender is draining. While {SenderBase} doesn't implement any means of doing so, derivations
27
- # of this class do.
28
- # @return [QueueBase] the queue instance that this sender is draining.
29
- attr_accessor :queue
30
-
31
- # The buffer size for a single batch of telemetry. This is the maximum number of items in a single service
32
- # request that this sender is going to send.
33
- # @return [Fixnum] the maximum number of items in a telemetry batch.
34
- attr_accessor :send_buffer_size
35
-
36
- # Immediately sends the data passed in to {#service_endpoint_uri}. If the service request fails, the passed in items
37
- # are pushed back to the {#queue}.
38
- # @param [Array<Contracts::Envelope>] data_to_send an array of {Contracts::Envelope} objects to send to the service.
39
- def send(data_to_send)
40
- uri = URI(@service_endpoint_uri)
41
- headers = {
42
- 'Accept' => 'application/json',
43
- 'Content-Type' => 'application/json; charset=utf-8',
44
- 'Content-Encoding' => 'gzip'
45
- }
46
- request = Net::HTTP::Post.new(uri.path, headers)
47
- # Use JSON.generate instead of to_json, otherwise it will default to ActiveSupport::JSON.encode for Rails app
48
- json = JSON.generate(data_to_send)
49
- compressed_data = compress(json)
50
- request.body = compressed_data
51
-
52
- http = Net::HTTP.new uri.hostname, uri.port
53
- if uri.scheme.downcase == 'https'
54
- http.use_ssl = true
55
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
56
- end
57
- response = http.request(request)
58
- end
59
-
60
- private
61
-
62
- def compress(string)
63
- wio = StringIO.new("w")
64
- w_gz = Zlib::GzipWriter.new wio, nil, nil
65
- w_gz.write(string)
66
- w_gz.close
67
- wio.string
68
- end
69
-
70
- end
71
- end
72
- end
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'openssl'
4
+ require 'stringio'
5
+ require 'zlib'
6
+
7
+ module ApplicationInsights
8
+ module Channel
9
+ # The base class for all types of senders for use in conjunction with an
10
+ # implementation of {QueueBase}. The queue will notify the sender that it
11
+ # needs to pick up items. The concrete sender implementation will listen to
12
+ # these notifications and will pull items from the queue using
13
+ # {QueueBase#pop} getting at most {#send_buffer_size} items.
14
+ # It will then call {#send} using the list of items pulled from the queue.
15
+ class SenderBase
16
+ # Initializes a new instance of the class.
17
+ # @param [String] service_endpoint_uri the address of the service to send
18
+ # telemetry data to.
19
+ def initialize(service_endpoint_uri)
20
+ @service_endpoint_uri = service_endpoint_uri
21
+ @queue = nil
22
+ @send_buffer_size = 100
23
+ end
24
+
25
+ # The service endpoint URI where this sender will send data to.
26
+ # @return [String] the service endpoint URI.
27
+ attr_accessor :service_endpoint_uri
28
+
29
+ # The queue that this sender is draining. While {SenderBase} doesn't
30
+ # implement any means of doing so, derivations of this class do.
31
+ # @return [QueueBase] the queue instance that this sender is draining.
32
+ attr_accessor :queue
33
+
34
+ # The buffer size for a single batch of telemetry. This is the maximum number
35
+ # of items in a single service request that this sender is going to send.
36
+ # @return [Fixnum] the maximum number of items in a telemetry batch.
37
+ attr_accessor :send_buffer_size
38
+
39
+ # Immediately sends the data passed in to {#service_endpoint_uri}. If the
40
+ # service request fails, the passed in items are pushed back to the {#queue}.
41
+ # @param [Array<Contracts::Envelope>] data_to_send an array of
42
+ # {Contracts::Envelope} objects to send to the service.
43
+ def send(data_to_send)
44
+ uri = URI(@service_endpoint_uri)
45
+ headers = {
46
+ 'Accept' => 'application/json',
47
+ 'Content-Type' => 'application/json; charset=utf-8',
48
+ 'Content-Encoding' => 'gzip'
49
+ }
50
+ request = Net::HTTP::Post.new(uri.path, headers)
51
+
52
+ # Use JSON.generate instead of to_json, otherwise it will
53
+ # default to ActiveSupport::JSON.encode for Rails app
54
+ json = JSON.generate(data_to_send)
55
+ compressed_data = compress(json)
56
+ request.body = compressed_data
57
+
58
+ http = Net::HTTP.new uri.hostname, uri.port
59
+ if uri.scheme.downcase == 'https'
60
+ http.use_ssl = true
61
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
62
+ end
63
+
64
+ response = http.request(request)
65
+ http.finish if http.started?
66
+ end
67
+
68
+ private
69
+
70
+ def compress(string)
71
+ wio = StringIO.new("w")
72
+ w_gz = Zlib::GzipWriter.new wio, nil, nil
73
+ w_gz.write(string)
74
+ w_gz.close
75
+ wio.string
76
+ end
77
+ end
78
+ end
79
+ end
@@ -1,39 +1,45 @@
1
- require_relative 'queue_base'
2
-
3
- module ApplicationInsights
4
- module Channel
5
- # A synchronous queue for use in conjunction with the {SynchronousSender}. The queue
6
- # will call {SenderBase#send} when it reaches {#max_queue_length}, or when the consumer
7
- # calls {#flush}.
8
- # @example
9
- # require 'application_insights'
10
- # require 'thread'
11
- # queue = ApplicationInsights::Channel::SynchronousQueue.new nil
12
- # queue.max_queue_length = 1
13
- # queue.push 1
14
- class SynchronousQueue < QueueBase
15
- # Initializes a new instance of the class.
16
- # @param [SenderBase] sender the sender object that will be used in conjunction with this queue.
17
- def initialize(sender)
18
- super sender
19
- end
20
-
21
- # Flushes the current queue by by calling {#sender}'s {SenderBase#send} method.
22
- def flush
23
- local_sender = @sender
24
- return unless local_sender
25
- while TRUE
26
- # get at most send_buffer_size items and send them
27
- data = []
28
- while data.length < local_sender.send_buffer_size
29
- item = pop()
30
- break if not item
31
- data.push item
32
- end
33
- break if data.length == 0
34
- local_sender.send(data)
35
- end
36
- end
37
- end
38
- end
39
- end
1
+ require_relative 'queue_base'
2
+
3
+ module ApplicationInsights
4
+ module Channel
5
+ # A synchronous queue for use in conjunction with the {SynchronousSender}.
6
+ # The queue will call {SenderBase#send} when it reaches {#max_queue_length},
7
+ # or when the consumer calls {#flush}.
8
+ #
9
+ # @example
10
+ # require 'application_insights'
11
+ # require 'thread'
12
+ # queue = ApplicationInsights::Channel::SynchronousQueue.new nil
13
+ # queue.max_queue_length = 1
14
+ # queue.push 1
15
+ class SynchronousQueue < QueueBase
16
+ # Initializes a new instance of the class.
17
+ # @param [SenderBase] sender the sender object that will be used in
18
+ # conjunction with this queue.
19
+ def initialize(sender)
20
+ super sender
21
+ end
22
+
23
+ # Flushes the current queue by by calling {#sender}'s
24
+ # {SenderBase#send} method.
25
+ def flush
26
+ local_sender = @sender
27
+ return unless local_sender
28
+
29
+ while true
30
+ # get at most send_buffer_size items and send them
31
+ data = []
32
+ while data.length < local_sender.send_buffer_size
33
+ item = pop()
34
+ break if not item
35
+ data.push item
36
+ end
37
+
38
+ break if data.length == 0
39
+
40
+ local_sender.send(data)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end