Added documentattion for channel classes

Other changes
- Hooked in Yard into Rake
- Small cahnges to README.md for it to look better in the generated docs
- Added additional development dependencies to gemfile
This commit is contained in:
Bogdan Berce 2014-12-20 16:18:30 -08:00
Родитель 1cc4573634
Коммит 60af91bfd2
11 изменённых файлов: 151 добавлений и 53 удалений

Просмотреть файл

@ -27,7 +27,7 @@ Once installed, you can send telemetry to Application Insights. Here are a few s
>**Note**: before you can send data to you will need an instrumentation key. Please see the [Getting an Application Insights Instrumentation Key](https://github.com/Microsoft/AppInsights-Home/wiki#getting-an-application-insights-instrumentation-key) section for more information.
**Sending a simple event telemetry item**
###Sending a simple event telemetry item###
```ruby
require 'application_insights'
tc = ApplicationInsights::TelemetryClient.new
@ -36,7 +36,7 @@ tc.track_event 'My event'
tc.flush
```
**Sending an event telemetry item with custom properties and measurements**
###Sending an event telemetry item with custom properties and measurements###
```ruby
require 'application_insights'
tc = ApplicationInsights::TelemetryClient.new
@ -45,7 +45,7 @@ tc.track_event 'My event', :properties => { 'custom property' => 'some value' },
tc.flush
```
**Sending a trace telemetry item with custom properties**
###Sending a trace telemetry item with custom properties###
```ruby
require 'application_insights'
tc = ApplicationInsights::TelemetryClient.new
@ -54,7 +54,7 @@ tc.track_trace 'My trace statement', :properties => { 'custom property' => 'some
tc.flush
```
**Sending a metric telemetry item (without and with optional values)**
###Sending a metric telemetry item (without and with optional values)###
```ruby
require 'application_insights'
tc = ApplicationInsights::TelemetryClient.new
@ -65,7 +65,7 @@ tc.track_metric 'My metric', 42, :kind => ApplicationInsights::Channel::Contract
tc.flush
```
**Sending an exception telemetry item with custom properties and measurements**
###Sending an exception telemetry item with custom properties and measurements###
```ruby
require 'application_insights'
tc = ApplicationInsights::TelemetryClient.new
@ -78,7 +78,7 @@ end
tc.flush
```
**Configuring context for a telemetry client instance**
###Configuring context for a telemetry client instance###
```ruby
require 'application_insights'
tc = ApplicationInsights::TelemetryClient.new
@ -94,7 +94,7 @@ tc.track_trace 'My trace with context'
tc.flush
```
**Configuring synchronous (default) channel properties**
###Configuring synchronous (default) channel properties###
```ruby
require 'application_insights'
tc = ApplicationInsights::TelemetryClient.new
@ -104,24 +104,24 @@ tc.channel.queue.max_queue_length = 10
tc.channel.sender.send_buffer_size = 5
```
**Configuring an asynchronous channel instead of the synchronous default**
###Configuring an asynchronous channel instead of the synchronous default###
```ruby
require 'application_insights'
sender = ApplicationInsights::Channel::AsynchronousSender.new
queue = ApplicationInsights::Channel::AsynchronousQueue.new sender
channel = ApplicationInsights::Channel::TelemetryChannel nil, queue
channel = ApplicationInsights::Channel::TelemetryChannel.new nil, queue
tc = ApplicationInsights::TelemetryClient.new channel
# Note: the event will be sent on a separate thread; if the app finishes before
# the thread finishes, the data is lost
tc.track_event 'My event'
```
**Configuring asynchronous channel properties**
###Configuring asynchronous channel properties###
```ruby
require 'application_insights'
sender = ApplicationInsights::Channel::AsynchronousSender.new
queue = ApplicationInsights::Channel::AsynchronousQueue.new sender
channel = ApplicationInsights::Channel::TelemetryChannel nil, queue
channel = ApplicationInsights::Channel::TelemetryChannel.new nil, queue
tc = ApplicationInsights::TelemetryClient.new channel
# flush telemetry if we have 10 or more telemetry items in our queue
tc.channel.queue.max_queue_length = 10

Просмотреть файл

@ -1,5 +1,6 @@
require "bundler/gem_tasks"
require 'rake/testtask'
require 'yard'
Rake::TestTask.new do |test|
test.libs << 'test'
@ -7,4 +8,8 @@ Rake::TestTask.new do |test|
test.verbose = true
end
task :default => [ :test, :build ]
YARD::Rake::YardocTask.new do |task|
task.files = ['lib/**/*.rb', '-', 'LICENSE.txt', 'README.md']
end
task :default => [ :test, :build, :yard ]

Просмотреть файл

@ -22,4 +22,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'bundler', '~> 1.7'
spec.add_development_dependency 'rake', '~> 10.0'
spec.add_development_dependency 'yard', '~> 0.8.7.6'
spec.add_development_dependency 'redcarpet', '~> 3.2.2'
end

Просмотреть файл

@ -6,6 +6,18 @@ module ApplicationInsights
# An asynchronous queue for use in conjunction with the {AsynchronousSender}. The queue
# will notify the sender that it needs to pick up items when it reaches {#max_queue_length}, or when the consumer
# calls {#flush} via the {#flush_notification} event.
# @example
# require 'application_insights'
# require 'thread'
# queue = ApplicationInsights::Channel::AsynchronousQueue.new nil
# Thread.new do
# sleep 1
# queue.push 1
# queue.flush
# end
# queue.flush_notification.wait
# queue.flush_notification.clear
# result = queue.pop
class AsynchronousQueue < QueueBase
# Initializes a new instance of the class.
# @param [SenderBase] sender the sender object that will be used in conjunction with this queue. In addition to
@ -26,13 +38,13 @@ module ApplicationInsights
# @param [Contracts::Envelope] item the telemetry envelope object to send to the service.
def push(item)
super item
@sender.start
@sender.start if @sender
end
# Flushes the current queue by notifying the {#sender} via the {#flush_notification} event.
def flush
@flush_notification.set
@sender.start
@sender.start if @sender
end
end
end

Просмотреть файл

@ -7,6 +7,17 @@ module ApplicationInsights
#
# An object of this type managers an internal flag that can be set to true via the {#set} method and reset via the
# {#clear} method. Calling the {#wait} method will block until the flag is set to true.
# @example
# require 'application_insights'
# require 'thread'
# event = ApplicationInsights::Channel::Event.new
# Thread.new do
# sleep 1
# event.set
# end
# puts 'Main screen turn on.'
# result = event.wait
# puts 'All your base are belong to us.'
class Event
# Initializes a new instance of the class.
def initialize

Просмотреть файл

@ -2,24 +2,30 @@ require 'thread'
module ApplicationInsights
module Channel
# The base class for all queues.
# The base class for all types of queues for use in conjunction with an implementation of {SenderBase}. The queue
# will notify the sender that it needs to pick up items when it reaches {#max_queue_length}, or when the consumer
# calls {#flush}.
class QueueBase
# Initializes a new instance of the queue class.
# Initializes a new instance of the class.
# @param [SenderBase] sender the sender object that will be used in conjunction with this queue.
def initialize(sender)
raise ArgumentError, 'Sender was required but not provided' unless sender
@queue = Queue.new
@max_queue_length = 500
@sender = sender
@sender.queue = self
@sender.queue = self if sender
end
# Gets or sets the maximum number of items that will be held by the queue before we force a send.
# The maximum number of items that will be held by the queue before the queue will call the {#flush} method.
# @return [Fixnum] the maximum queue size. (defaults to: 500)
attr_accessor :max_queue_length
# Gets the sender associated with this queue
# The sender that is associated with this queue that this queue will use to send data to the service.
# @return [SenderBase] the sender object.
attr_reader :sender
# Adds a single item to the queue.
# Adds the passed in item object to the queue and calls {#flush} if the size of the queue is larger
# than {#max_queue_length}. This method does nothing if the passed in item is nil.
# @param [Contracts::Envelope] item the telemetry envelope object to send to the service.
def push(item)
unless item
return
@ -31,7 +37,8 @@ module ApplicationInsights
end
end
# Gets a single item from the queue. If no item is available, return nil.
# Pops a single item from the queue and returns it. If the queue is empty, this method will return nil.
# @return [Contracts::Envelope] a telemetry envelope object or nil if the queue is empty.
def pop
begin
return @queue.pop(TRUE)
@ -40,7 +47,8 @@ module ApplicationInsights
end
end
# Flushes the current queue to the passed in sender.
# Flushes the current queue by notifying the {#sender}. This method needs to be overridden by a concrete
# implementations of the queue class.
def flush
end
end

Просмотреть файл

@ -3,9 +3,13 @@ require 'net/http'
module ApplicationInsights
module Channel
# The base class for all of our senders.
# The base class for all types of senders for use in conjunction with an implementation of {QueueBase}. The queue
# will notify the sender that it needs to pick up items. The concrete sender implementation will listen to these
# notifications and will pull items from the queue using {QueueBase#pop} getting at most {#send_buffer_size} items.
# it will then call {#send} using the list of items pulled from the queue.
class SenderBase
# Initializes a new instance of the sender class.
# Initializes a new instance of the class.
# @param [String] service_endpoint_uri the address of the service to send telemetry data to.
def initialize(service_endpoint_uri)
raise ArgumentError, 'Service endpoint URI was required but not provided' unless service_endpoint_uri
@service_endpoint_uri = service_endpoint_uri
@ -13,16 +17,23 @@ module ApplicationInsights
@send_buffer_size = 100
end
# Gets the service endpoint URI property. This is where we send data to.
# The service endpoint URI where this sender will send data to.
# @return [String] the service endpoint URI.
attr_accessor :service_endpoint_uri
# The queue that we will be draining
# The queue that this sender is draining. While {SenderBase} doesn't implement any means of doing so, derivations
# of this class do.
# @return [QueueBase] the queue instance that this sender is draining.
attr_accessor :queue
# Gets or sets the buffer size for a single batch of telemetry. This is the maximum number of items in a single service request we are going to send.
# The buffer size for a single batch of telemetry. This is the maximum number of items in a single service
# request that this sender is going to send.
# @return [Fixnum] the maximum number of items in a telemetry batch.
attr_accessor :send_buffer_size
# Sends the data to send list to the service immediately.
# Immediately sends the data passed in to {#service_endpoint_uri}. If the service request fails, the passed in items
# are pushed back to the {#queue}.
# @param [Array<Contracts::Envelope>] data_to_send an array of {Contracts::Envelope} objects to send to the service.
def send(data_to_send)
uri = URI(@service_endpoint_uri)
request = Net::HTTP::Post.new(uri.path, { 'Accept' => 'application/json', 'Content-Type' => 'application/json; charset=utf-8' })

Просмотреть файл

@ -2,25 +2,36 @@ require_relative 'queue_base'
module ApplicationInsights
module Channel
# A synchronous queue for use in conjunction with the SynchronousSender. The queue will flush either when it reaches max_queue_length or when someone calls flush().
# A synchronous queue for use in conjunction with the {SynchronousSender}. The queue
# will call {SenderBase#send} when it reaches {#max_queue_length}, or when the consumer
# calls {#flush}.
# @example
# require 'application_insights'
# require 'thread'
# queue = ApplicationInsights::Channel::SynchronousQueue.new nil
# queue.max_queue_length = 1
# queue.push 1
class SynchronousQueue < QueueBase
# Initializes a new instance of the synchronous queue class.
# Initializes a new instance of the class.
# @param [SenderBase] sender the sender object that will be used in conjunction with this queue.
def initialize(sender)
super sender
end
# Flushes the current queue to the passed in sender.
# Flushes the current queue by by calling {#sender}'s {SenderBase#send} method.
def flush
local_sender = @sender
return unless local_sender
while TRUE
# get at most send_buffer_size items and send them
data = []
while data.length < @sender.send_buffer_size
while data.length < local_sender.send_buffer_size
item = pop()
break if not item
data.push item
end
break if data.length == 0
@sender.send(data)
local_sender.send(data)
end
end
end

Просмотреть файл

@ -2,9 +2,11 @@ require_relative 'sender_base'
module ApplicationInsights
module Channel
# A synchronous sender that works in conjunction with SynchronousQueue.
# A synchronous sender that works in conjunction with the {SynchronousQueue}. The queue will call {#send} on the
# current instance with the data to send.
class SynchronousSender < SenderBase
# Initializes a new instance of the synchronous sender class.
# Initializes a new instance of the class.
# @param [String] service_endpoint_uri the address of the service to send telemetry data to.
def initialize(service_endpoint_uri='https://dc.services.visualstudio.com/v2/track')
super service_endpoint_uri
end

Просмотреть файл

@ -9,31 +9,48 @@ require_relative 'contracts/internal'
module ApplicationInsights
module Channel
# The telemetry channel is responsible for constructing an envelope an sending it.
# The telemetry channel is responsible for constructing a {Contracts::Envelope} object from the passed in
# data and specified telemetry context.
# @example
# require 'application_insights'
# channel = ApplicationInsights::Channel::TelemetryChannel.new
# event = ApplicationInsights::Channel::Contracts::EventData.new :name => 'My event'
# channel.write event
class TelemetryChannel
# Initializes a new instance of the telemetry channel class.
# Initializes a new instance of the class.
# @param [TelemetryContext] context the telemetry context to use when sending telemetry data.
# @param [QueueBase] queue the queue to enqueue the resulting {Contracts::Envelope} to.
def initialize(context=nil, queue=nil)
@context = context || TelemetryContext.new
@queue = queue || SynchronousQueue.new(SynchronousSender.new)
end
# Gets the context associated with this channel.
# The context associated with this channel. All {Contracts::Envelope} objects created by this channel will use
# this value if it's present or if none is specified as part of the {#write} call.
# @return [TelemetryContext] the context instance (defaults to: TelemetryContext.new)
attr_reader :context
# Gets the queue associated with this channel.
# The queue associated with this channel. All {Contracts::Envelope} objects created by this channel will be
# pushed to this queue.
# @return [QueueBase] the queue instance (defaults to: SynchronousQueue.new)
attr_reader :queue
# Gets the sender associated with this channel.
# The sender associated with this channel. This instance will be used to transmit telemetry to the service.
# @return [SenderBase] the sender instance (defaults to: SynchronousSender.new)
def sender
@queue.sender
end
# Flushes the current queue.
# Flushes the enqueued data by calling {QueueBase#flush}.
def flush
@queue.flush
end
# Writes the passed in data to the sending queue.
# Enqueues the passed in data to the {#queue}. If the caller specifies a context as well, it will take precedence
# over the instance in {#context}.
# @param [Object] data the telemetry data to send. This will be wrapped in an {Contracts::Envelope} before being
# enqueued to the {#queue}.
# @param [TelemetryContext] context the override context to use when constructing the {Contracts::Envelope}.
def write(data, context=nil)
local_context = context || @context
raise ArgumentError, 'Context was required but not provided' unless local_context

Просмотреть файл

@ -7,9 +7,20 @@ require_relative 'contracts/location'
module ApplicationInsights
module Channel
# Represents a context for sending telemetry to the Application Insights service.
# Represents the context for sending telemetry to the Application Insights service.
# @example
# require 'application_insights'
# context = ApplicationInsights::Channel::TelemetryContext.new
# context.instrumentation_key = '<YOUR INSTRUMENTATION KEY GOES HERE>'
# context.application.id = 'My application'
# context.application.ver = '1.2.3'
# context.device.id = 'My current device'
# context.device.oem_name = 'Asus'
# context.device.model = 'X31A'
# context.device.type = "Other"
# context.user.id = 'santa@northpole.net'
class TelemetryContext
# Initializes a new instance of the TelemetryContext class.
# Initializes a new instance of the class.
def initialize
@instrumentation_key = nil
@application = Contracts::Application.new
@ -21,28 +32,36 @@ module ApplicationInsights
@properties = {}
end
# Gets or sets the instrumentation key.
# The instrumentation key that is used to identify which Application Insights application this data is for.
# @return [String] the instrumentation key.
attr_accessor :instrumentation_key
# Gets or sets the application context.
# The application context. This contains properties of the application you are running.
# @return [Contracts::Application] the context object.
attr_accessor :application
# Gets or sets the device context.
# The device context. This contains properties of the device you are running on.
# @return [Contracts::Device] the context object.
attr_accessor :device
# Gets or sets the user context.
# The user context. This contains properties of the user you are generating telemetry for.
# @return [Contracts::User] the context object.
attr_accessor :user
# Gets or sets the session context.
# The session context. This contains properties of the session you are generating telemetry for.
# @return [Contracts::Session] the context object.
attr_accessor :session
# Gets or sets the operation context.
# The operation context. This contains properties of the operation you are generating telemetry for.
# @return [Contracts::Operation] the context object.
attr_accessor :operation
# Gets or sets the location context.
# The location context. This contains properties of the location you are generating telemetry from.
# @return [Contracts::Location] the context object.
attr_accessor :location
# Gets a dictionary of application-defined property values.
# The property context. This contains free-form properties that you can add to your telemetry.
# @return [Hash<String, String>] the context object.
attr_reader :properties
end
end