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.
- checksums.yaml +6 -14
- data/.travis.yml +21 -9
- data/CONTRIBUTING.md +30 -0
- data/Gemfile +4 -4
- data/LICENSE.txt +11 -11
- data/README.md +13 -14
- data/Rakefile +14 -14
- data/application_insights.gemspec +28 -29
- data/lib/application_insights.rb +9 -9
- data/lib/application_insights/channel/asynchronous_queue.rb +58 -51
- data/lib/application_insights/channel/asynchronous_sender.rb +132 -123
- data/lib/application_insights/channel/contracts/application.rb +14 -53
- data/lib/application_insights/channel/contracts/cloud.rb +14 -0
- data/lib/application_insights/channel/contracts/data.rb +14 -48
- data/lib/application_insights/channel/contracts/data_point.rb +24 -130
- data/lib/application_insights/channel/contracts/data_point_type.rb +7 -16
- data/lib/application_insights/channel/contracts/dependency_kind.rb +9 -19
- data/lib/application_insights/channel/contracts/dependency_source_type.rb +9 -19
- data/lib/application_insights/channel/contracts/device.rb +28 -257
- data/lib/application_insights/channel/contracts/envelope.rb +40 -266
- data/lib/application_insights/channel/contracts/event_data.rb +28 -77
- data/lib/application_insights/channel/contracts/exception_data.rb +37 -140
- data/lib/application_insights/channel/contracts/exception_details.rb +28 -129
- data/lib/application_insights/channel/contracts/internal.rb +14 -53
- data/lib/application_insights/channel/contracts/json_serializable.rb +59 -59
- data/lib/application_insights/channel/contracts/location.rb +16 -36
- data/lib/application_insights/channel/contracts/message_data.rb +24 -77
- data/lib/application_insights/channel/contracts/metric_data.rb +27 -60
- data/lib/application_insights/channel/contracts/operation.rb +19 -121
- data/lib/application_insights/channel/contracts/page_view_data.rb +30 -111
- data/lib/application_insights/channel/contracts/remote_dependency_data.rb +56 -260
- data/lib/application_insights/channel/contracts/request_data.rb +36 -176
- data/lib/application_insights/channel/contracts/session.rb +15 -70
- data/lib/application_insights/channel/contracts/severity_level.rb +13 -25
- data/lib/application_insights/channel/contracts/stack_frame.rb +17 -94
- data/lib/application_insights/channel/contracts/user.rb +19 -104
- data/lib/application_insights/channel/event.rb +68 -64
- data/lib/application_insights/channel/queue_base.rb +65 -62
- data/lib/application_insights/channel/sender_base.rb +79 -72
- data/lib/application_insights/channel/synchronous_queue.rb +45 -39
- data/lib/application_insights/channel/synchronous_sender.rb +17 -15
- data/lib/application_insights/channel/telemetry_channel.rb +120 -102
- data/lib/application_insights/channel/telemetry_context.rb +85 -68
- data/lib/application_insights/rack/track_request.rb +87 -84
- data/lib/application_insights/telemetry_client.rb +229 -217
- data/lib/application_insights/unhandled_exception.rb +49 -47
- data/lib/application_insights/version.rb +3 -3
- data/test/application_insights.rb +8 -9
- data/test/application_insights/channel/contracts/test_application.rb +44 -44
- data/test/application_insights/channel/contracts/test_cloud.rb +44 -0
- data/test/application_insights/channel/contracts/test_data.rb +44 -44
- data/test/application_insights/channel/contracts/test_data_point.rb +109 -109
- data/test/application_insights/channel/contracts/test_device.rb +200 -200
- data/test/application_insights/channel/contracts/test_envelope.rb +209 -209
- data/test/application_insights/channel/contracts/test_event_data.rb +62 -62
- data/test/application_insights/channel/contracts/test_exception_data.rb +111 -111
- data/test/application_insights/channel/contracts/test_exception_details.rb +106 -106
- data/test/application_insights/channel/contracts/test_internal.rb +44 -44
- data/test/application_insights/channel/contracts/test_location.rb +70 -31
- data/test/application_insights/channel/contracts/test_message_data.rb +66 -66
- data/test/application_insights/channel/contracts/test_metric_data.rb +50 -50
- data/test/application_insights/channel/contracts/test_operation.rb +109 -96
- data/test/application_insights/channel/contracts/test_page_view_data.rb +88 -88
- data/test/application_insights/channel/contracts/test_remote_dependency_data.rb +209 -209
- data/test/application_insights/channel/contracts/test_request_data.rb +153 -153
- data/test/application_insights/channel/contracts/test_session.rb +57 -57
- data/test/application_insights/channel/contracts/test_stack_frame.rb +83 -83
- data/test/application_insights/channel/contracts/test_user.rb +96 -83
- data/test/application_insights/channel/test_asynchronous_queue.rb +47 -47
- data/test/application_insights/channel/test_asynchronous_sender.rb +80 -80
- data/test/application_insights/channel/test_event.rb +52 -52
- data/test/application_insights/channel/test_queue_base.rb +88 -88
- data/test/application_insights/channel/test_sender_base.rb +87 -87
- data/test/application_insights/channel/test_synchronous_queue.rb +27 -27
- data/test/application_insights/channel/test_synchronous_sender.rb +10 -10
- data/test/application_insights/channel/test_telemetry_channel.rb +126 -102
- data/test/application_insights/channel/test_telemetry_context.rb +82 -74
- data/test/application_insights/mock_sender.rb +37 -37
- data/test/application_insights/rack/test_track_request.rb +142 -139
- data/test/application_insights/test_telemetry_client.rb +133 -123
- data/test/application_insights/test_unhandled_exception.rb +23 -24
- 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
|
9
|
-
# {#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# puts '
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
6
|
-
# will notify the sender that it
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@
|
15
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
request
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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}.
|
6
|
-
# will call {SenderBase#send} when it reaches {#max_queue_length},
|
7
|
-
# calls {#flush}.
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# require '
|
11
|
-
#
|
12
|
-
# queue
|
13
|
-
# queue.
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|