application_insights 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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