diff --git a/lib/application_insights.rb b/lib/application_insights.rb index eefc7e7..0a683d4 100644 --- a/lib/application_insights.rb +++ b/lib/application_insights.rb @@ -4,6 +4,6 @@ require_relative 'application_insights/version' module ApplicationInsights module Rack - autoload :TrackRequest, "application_insights/rack/track_request" + autoload :TrackRequest, "application_insights/rack/track_request" end end diff --git a/lib/application_insights/channel/asynchronous_queue.rb b/lib/application_insights/channel/asynchronous_queue.rb index f29f4b1..333f696 100644 --- a/lib/application_insights/channel/asynchronous_queue.rb +++ b/lib/application_insights/channel/asynchronous_queue.rb @@ -3,9 +3,11 @@ require_relative 'queue_base' module ApplicationInsights module Channel - # 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. + # 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' @@ -20,32 +22,37 @@ module ApplicationInsights # 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 - # the sender object must support a {AsynchronousSender#start} method which is invoked - # each time an item is pushed to the queue as well as use the {#flush_notification} event. + # @param [SenderBase] sender the sender object that will be used in + # conjunction with this queue. In addition to the sender object must + # support a {AsynchronousSender#start} method which is invoked each time + # an item is pushed to the queue as well as use the {#flush_notification} + # event. def initialize(sender) @flush_notification = Event.new super sender end - # The flush notification {ApplicationInsights::Channel::Event} that the {#sender} will use to get notified - # that a flush is needed. + # The flush notification {ApplicationInsights::Channel::Event} that the {#sender} + # will use to get notified that a flush is needed. # @return [Event] object that the {#sender} can wait on. attr_reader :flush_notification - # Adds the passed in item object to the queue and notifies the {#sender} to start an asynchronous send operation + # Adds the passed in item object to the queue and notifies the {#sender} + # to start an asynchronous send operation # by calling {AsynchronousSender#start}. - # @param [Contracts::Envelope] item the telemetry envelope object to send to the service. + # @param [Contracts::Envelope] item the telemetry envelope object to send + # to the service. def push(item) super item @sender.start if @sender end - # Flushes the current queue by notifying the {#sender} via the {#flush_notification} event. + # Flushes the current queue by notifying the {#sender} via the + # {#flush_notification} event. def flush @flush_notification.set @sender.start if @sender end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/channel/asynchronous_sender.rb b/lib/application_insights/channel/asynchronous_sender.rb index 1f5644a..6457565 100644 --- a/lib/application_insights/channel/asynchronous_sender.rb +++ b/lib/application_insights/channel/asynchronous_sender.rb @@ -3,20 +3,25 @@ require 'thread' module ApplicationInsights module Channel - # An asynchronous sender that works in conjunction with the {AsynchronousQueue}. The sender object will start a - # worker thread that will pull items from the {#queue}. The thread will be created when the client calls {#start} and - # will check for queue items every {#send_interval} seconds. The worker thread can also be forced to check the queue - # by setting the {AsynchronousQueue#flush_notification} event. + # An asynchronous sender that works in conjunction with the {AsynchronousQueue}. + # The sender object will start a worker thread that will pull items from the + # {#queue}. The thread will be created when the client calls {#start} and + # will check for queue items every {#send_interval} seconds. The worker thread + # can also be forced to check the queue by setting the + # {AsynchronousQueue#flush_notification} event. # # - If no items are found, the thread will go back to sleep. - # - If items are found, the worker thread will send items to the specified service in batches of {#send_buffer_size}. + # - If items are found, the worker thread will send items to the specified + # service in batches of {#send_buffer_size}. # - # If no queue items are found for {#send_time} seconds, the worker thread will shut down (and {#start} will - # need to be called again). + # If no queue items are found for {#send_time} seconds, the worker thread + # will shut down (and {#start} will need to be called again). class AsynchronousSender < SenderBase + SERVICE_ENDPOINT_URI = 'https://dc.services.visualstudio.com/v2/track' # 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') + # @param [String] service_endpoint_uri the address of the service to send + # telemetry data to. + def initialize(service_endpoint_uri = SERVICE_ENDPOINT_URI) @send_interval = 1.0 @send_remaining_time = 0 @send_time = 3.0 @@ -26,32 +31,34 @@ module ApplicationInsights super service_endpoint_uri end - # The time span in seconds at which the the worker thread will check the {#queue} for items (defaults to: 1.0). + # The time span in seconds at which the the worker thread will check the + # {#queue} for items (defaults to: 1.0). # @return [Fixnum] the interval in seconds. attr_accessor :send_interval - # The time span in seconds for which the worker thread will stay alive if no items are found in the {#queue} (defaults to 3.0). + # The time span in seconds for which the worker thread will stay alive if + # no items are found in the {#queue} (defaults to 3.0). # @return [Fixnum] the interval in seconds. attr_accessor :send_time - # The worker thread which checks queue items and send data every (#send_interval) seconds or upon flush. + # The worker thread which checks queue items and send data every + # (#send_interval) seconds or upon flush. # @return [Thread] the work thread attr_reader :work_thread - # Calling this method will create a worker thread that checks the {#queue} every {#send_interval} seconds for - # a total duration of {#send_time} seconds for new items. If a worker thread has already been created, calling - # this method does nothing. + # Calling this method will create a worker thread that checks the {#queue} + # every {#send_interval} seconds for a total duration of {#send_time} + # seconds for new items. If a worker thread has already been created, + # calling this method does nothing. def start @start_notification_processed = false # Maintain one working thread at one time - if !@work_thread + unless @work_thread @lock_work_thread.synchronize do - if !@work_thread - local_send_interval = (@send_interval < 0.1) ? 0.1 : @send_interval - @send_remaining_time = (@send_time < local_send_interval) ? local_send_interval : @send_time - @work_thread = Thread.new do - run - end + unless @work_thread + local_send_interval = [@send_interval, 0.1].max + @send_remaining_time = [@send_time, local_send_interval].max + @work_thread = Thread.new { run } @work_thread.abort_on_exception = false end end @@ -63,56 +70,58 @@ module ApplicationInsights def run # save the queue locally local_queue = @queue - if local_queue == nil + if local_queue.nil? @work_thread = nil return end begin - # fix up the send interval (can't be lower than 100ms) - local_send_interval = (@send_interval < 0.1) ? 0.1 : @send_interval - while TRUE - @start_notification_processed = true - while TRUE - # get at most @send_buffer_size items from the queue - counter = @send_buffer_size - data = [] - while counter > 0 - item = local_queue.pop - break if not item - data.push item - counter -= 1 + # fix up the send interval (can't be lower than 100ms) + local_send_interval = [@send_interval, 0.1].max + + while true + @start_notification_processed = true + while true + # get at most @send_buffer_size items from the queue + data = [] + @send_buffer_size.downto(1) do + item = local_queue.pop + break if not item + data.push item + end + + # if we didn't get any items from the queue, we're done here + break if data.length == 0 + + # reset the send time + @send_remaining_time = @send_time + + # finally send the data + send data end - # if we didn't get any items from the queue, we're done here - break if data.length == 0 + # wait at most @send_interval ms (or until we get signalled) + result = local_queue.flush_notification.wait local_send_interval + if result + local_queue.flush_notification.clear + next + end - # reset the send time - @send_remaining_time = @send_time - - # finally send the data - send data + # decrement the remaining time + @send_remaining_time -= local_send_interval + # If remaining time <=0 and there is no start notification unprocessed, + # then stop the working thread + if @send_remaining_time <= 0 && @start_notification_processed + # Note: there is still a chance some start notification could be + # missed, e.g., the start method got triggered between the above and + # following line. However the data is not lost as it would be + # processed later when next start notification comes after the worker + # thread stops. The cost to ensure no notification miss is high where + # a lock is required each time the start method calls. + @work_thread = nil + break + end end - - # wait at most @send_interval ms (or until we get signalled) - result = local_queue.flush_notification.wait local_send_interval - if result - local_queue.flush_notification.clear - next - end - - # decrement the remaining time - @send_remaining_time -= local_send_interval - # If remaining time <=0 and there is no start notification unprocessed, then stop the working thread - if @send_remaining_time <= 0 && @start_notification_processed - # Note: there is still a chance some start notification could be missed, e.g., the start method - # got triggered between the above and following line. However the data is not lost as it would be processed - # later when next start notification comes after the worker thread stops. The cost to ensure no - # notification miss is high where a lock is required each time the start method calls. - @work_thread = nil - break - end - end rescue # Make sure work_thread sets to nil when it terminates abnormally @work_thread = nil @@ -120,4 +129,4 @@ module ApplicationInsights end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/channel/contracts/application.rb b/lib/application_insights/channel/contracts/application.rb index 82e407f..8b7a284 100644 --- a/lib/application_insights/channel/contracts/application.rb +++ b/lib/application_insights/channel/contracts/application.rb @@ -1,53 +1,14 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Application. - class Application < JsonSerializable - # Initializes a new instance of the Application class. - def initialize(options={}) - defaults = { - 'ai.application.ver' => nil, - 'ai.application.build' => nil - } - values = { - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values.fetch('ai.application.ver') { - @values['ai.application.ver'] = nil - } - end - - # Sets the ver property. - def ver=(value) - if value == @defaults['ai.application.ver'] - @values.delete 'ai.application.ver' if @values.key? 'ai.application.ver' - else - @values['ai.application.ver'] = value - end - end - - # Gets the build property. - def build - @values.fetch('ai.application.build') { - @values['ai.application.build'] = nil - } - end - - # Sets the build property. - def build=(value) - if value == @defaults['ai.application.build'] - @values.delete 'ai.application.build' if @values.key? 'ai.application.build' - else - @values['ai.application.build'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class Application + include JsonSerializable + + attr_accessor :ver, :build + + attribute_mapping( + ver: 'ai.application.ver', + build: 'ai.application.build' + ) end end diff --git a/lib/application_insights/channel/contracts/data.rb b/lib/application_insights/channel/contracts/data.rb index edae0a8..c7184ed 100644 --- a/lib/application_insights/channel/contracts/data.rb +++ b/lib/application_insights/channel/contracts/data.rb @@ -1,48 +1,14 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Data. - class Data < JsonSerializable - # Initializes a new instance of the Data class. - def initialize(options={}) - defaults = { - 'baseType' => nil, - 'baseData' => nil - } - values = { - 'baseData' => nil - } - super defaults, values, options - end - - # Gets the base_type property. - def base_type - @values.fetch('baseType') { - @values['baseType'] = nil - } - end - - # Sets the base_type property. - def base_type=(value) - if value == @defaults['baseType'] - @values.delete 'baseType' if @values.key? 'baseType' - else - @values['baseType'] = value - end - end - - # Gets the base_data property. - def base_data - @values['baseData'] - end - - # Sets the base_data property. - def base_data=(value) - @values['baseData'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class Data + include JsonSerializable + + attr_accessor :base_type, :base_data + + attribute_mapping( + base_type: 'baseType', + base_data: 'baseData' + ) end end diff --git a/lib/application_insights/channel/contracts/data_point.rb b/lib/application_insights/channel/contracts/data_point.rb index 63834b8..5661107 100644 --- a/lib/application_insights/channel/contracts/data_point.rb +++ b/lib/application_insights/channel/contracts/data_point.rb @@ -1,130 +1,24 @@ require_relative 'json_serializable' +require_relative 'data_point_type' -module ApplicationInsights - module Channel - module Contracts - require_relative 'data_point_type' - # Data contract class for type DataPoint. - class DataPoint < JsonSerializable - # Initializes a new instance of the DataPoint class. - def initialize(options={}) - defaults = { - 'name' => nil, - 'kind' => DataPointType::MEASUREMENT, - 'value' => nil, - 'count' => nil, - 'min' => nil, - 'max' => nil, - 'stdDev' => nil - } - values = { - 'name' => nil, - 'kind' => DataPointType::MEASUREMENT, - 'value' => nil - } - super defaults, values, options - end - - # Gets the name property. - def name - @values['name'] - end - - # Sets the name property. - def name=(value) - @values['name'] = value - end - - # Gets the kind property. - def kind - @values.fetch('kind') { - @values['kind'] = DataPointType::MEASUREMENT - } - end - - # Sets the kind property. - def kind=(value) - if value == @defaults['kind'] - @values.delete 'kind' if @values.key? 'kind' - else - @values['kind'] = value - end - end - - # Gets the value property. - def value - @values['value'] - end - - # Sets the value property. - def value=(value) - @values['value'] = value - end - - # Gets the count property. - def count - @values.fetch('count') { - @values['count'] = nil - } - end - - # Sets the count property. - def count=(value) - if value == @defaults['count'] - @values.delete 'count' if @values.key? 'count' - else - @values['count'] = value - end - end - - # Gets the min property. - def min - @values.fetch('min') { - @values['min'] = nil - } - end - - # Sets the min property. - def min=(value) - if value == @defaults['min'] - @values.delete 'min' if @values.key? 'min' - else - @values['min'] = value - end - end - - # Gets the max property. - def max - @values.fetch('max') { - @values['max'] = nil - } - end - - # Sets the max property. - def max=(value) - if value == @defaults['max'] - @values.delete 'max' if @values.key? 'max' - else - @values['max'] = value - end - end - - # Gets the std_dev property. - def std_dev - @values.fetch('stdDev') { - @values['stdDev'] = nil - } - end - - # Sets the std_dev property. - def std_dev=(value) - if value == @defaults['stdDev'] - @values.delete 'stdDev' if @values.key? 'stdDev' - else - @values['stdDev'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class DataPoint + include JsonSerializable + + attr_accessor :name, :kind, :value, :count, :min, :max, :std_dev + + attribute_mapping( + name: 'name', + kind: 'kind', + value: 'value', + count: 'count', + min: 'min', + max: 'max', + std_dev: 'stdDev' + ) + + def kind + @kind ||= DataPointType::MEASUREMENT end end end diff --git a/lib/application_insights/channel/contracts/data_point_type.rb b/lib/application_insights/channel/contracts/data_point_type.rb index 71f7d71..f9816e4 100644 --- a/lib/application_insights/channel/contracts/data_point_type.rb +++ b/lib/application_insights/channel/contracts/data_point_type.rb @@ -1,16 +1,7 @@ -require_relative 'json_serializable' +module ApplicationInsights::Channel::Contracts + class DataPointType + MEASUREMENT = 0 -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type DataPointType. - class DataPointType - # Enumeration value MEASUREMENT. - MEASUREMENT = 0 - - # Enumeration value AGGREGATION. - AGGREGATION = 1 - end - end + AGGREGATION = 1 end end diff --git a/lib/application_insights/channel/contracts/dependency_kind.rb b/lib/application_insights/channel/contracts/dependency_kind.rb index a744b93..38a4414 100644 --- a/lib/application_insights/channel/contracts/dependency_kind.rb +++ b/lib/application_insights/channel/contracts/dependency_kind.rb @@ -1,19 +1,9 @@ -require_relative 'json_serializable' +module ApplicationInsights::Channel::Contracts + class DependencyKind + SQL = 0 -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type DependencyKind. - class DependencyKind - # Enumeration value SQL. - SQL = 0 - - # Enumeration value HTTP. - HTTP = 1 - - # Enumeration value OTHER. - OTHER = 2 - end - end + HTTP = 1 + + OTHER = 2 end end diff --git a/lib/application_insights/channel/contracts/dependency_source_type.rb b/lib/application_insights/channel/contracts/dependency_source_type.rb index 1d525b5..a68dad7 100644 --- a/lib/application_insights/channel/contracts/dependency_source_type.rb +++ b/lib/application_insights/channel/contracts/dependency_source_type.rb @@ -1,19 +1,9 @@ -require_relative 'json_serializable' +module ApplicationInsights::Channel::Contracts + class DependencySourceType + UNDEFINED = 0 -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type DependencySourceType. - class DependencySourceType - # Enumeration value UNDEFINED. - UNDEFINED = 0 - - # Enumeration value AIC. - AIC = 1 - - # Enumeration value APMC. - APMC = 2 - end - end + AIC = 1 + + APMC = 2 end end diff --git a/lib/application_insights/channel/contracts/device.rb b/lib/application_insights/channel/contracts/device.rb index 864acdb..df94fc7 100644 --- a/lib/application_insights/channel/contracts/device.rb +++ b/lib/application_insights/channel/contracts/device.rb @@ -1,257 +1,28 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Device. - class Device < JsonSerializable - # Initializes a new instance of the Device class. - def initialize(options={}) - defaults = { - 'ai.device.id' => nil, - 'ai.device.ip' => nil, - 'ai.device.language' => nil, - 'ai.device.locale' => nil, - 'ai.device.model' => nil, - 'ai.device.network' => nil, - 'ai.device.oemName' => nil, - 'ai.device.os' => nil, - 'ai.device.osVersion' => nil, - 'ai.device.roleInstance' => nil, - 'ai.device.roleName' => nil, - 'ai.device.screenResolution' => nil, - 'ai.device.type' => nil, - 'ai.device.machineName' => nil - } - values = { - } - super defaults, values, options - end - - # Gets the id property. - def id - @values.fetch('ai.device.id') { - @values['ai.device.id'] = nil - } - end - - # Sets the id property. - def id=(value) - if value == @defaults['ai.device.id'] - @values.delete 'ai.device.id' if @values.key? 'ai.device.id' - else - @values['ai.device.id'] = value - end - end - - # Gets the ip property. - def ip - @values.fetch('ai.device.ip') { - @values['ai.device.ip'] = nil - } - end - - # Sets the ip property. - def ip=(value) - if value == @defaults['ai.device.ip'] - @values.delete 'ai.device.ip' if @values.key? 'ai.device.ip' - else - @values['ai.device.ip'] = value - end - end - - # Gets the language property. - def language - @values.fetch('ai.device.language') { - @values['ai.device.language'] = nil - } - end - - # Sets the language property. - def language=(value) - if value == @defaults['ai.device.language'] - @values.delete 'ai.device.language' if @values.key? 'ai.device.language' - else - @values['ai.device.language'] = value - end - end - - # Gets the locale property. - def locale - @values.fetch('ai.device.locale') { - @values['ai.device.locale'] = nil - } - end - - # Sets the locale property. - def locale=(value) - if value == @defaults['ai.device.locale'] - @values.delete 'ai.device.locale' if @values.key? 'ai.device.locale' - else - @values['ai.device.locale'] = value - end - end - - # Gets the model property. - def model - @values.fetch('ai.device.model') { - @values['ai.device.model'] = nil - } - end - - # Sets the model property. - def model=(value) - if value == @defaults['ai.device.model'] - @values.delete 'ai.device.model' if @values.key? 'ai.device.model' - else - @values['ai.device.model'] = value - end - end - - # Gets the network property. - def network - @values.fetch('ai.device.network') { - @values['ai.device.network'] = nil - } - end - - # Sets the network property. - def network=(value) - if value == @defaults['ai.device.network'] - @values.delete 'ai.device.network' if @values.key? 'ai.device.network' - else - @values['ai.device.network'] = value - end - end - - # Gets the oem_name property. - def oem_name - @values.fetch('ai.device.oemName') { - @values['ai.device.oemName'] = nil - } - end - - # Sets the oem_name property. - def oem_name=(value) - if value == @defaults['ai.device.oemName'] - @values.delete 'ai.device.oemName' if @values.key? 'ai.device.oemName' - else - @values['ai.device.oemName'] = value - end - end - - # Gets the os property. - def os - @values.fetch('ai.device.os') { - @values['ai.device.os'] = nil - } - end - - # Sets the os property. - def os=(value) - if value == @defaults['ai.device.os'] - @values.delete 'ai.device.os' if @values.key? 'ai.device.os' - else - @values['ai.device.os'] = value - end - end - - # Gets the os_version property. - def os_version - @values.fetch('ai.device.osVersion') { - @values['ai.device.osVersion'] = nil - } - end - - # Sets the os_version property. - def os_version=(value) - if value == @defaults['ai.device.osVersion'] - @values.delete 'ai.device.osVersion' if @values.key? 'ai.device.osVersion' - else - @values['ai.device.osVersion'] = value - end - end - - # Gets the role_instance property. - def role_instance - @values.fetch('ai.device.roleInstance') { - @values['ai.device.roleInstance'] = nil - } - end - - # Sets the role_instance property. - def role_instance=(value) - if value == @defaults['ai.device.roleInstance'] - @values.delete 'ai.device.roleInstance' if @values.key? 'ai.device.roleInstance' - else - @values['ai.device.roleInstance'] = value - end - end - - # Gets the role_name property. - def role_name - @values.fetch('ai.device.roleName') { - @values['ai.device.roleName'] = nil - } - end - - # Sets the role_name property. - def role_name=(value) - if value == @defaults['ai.device.roleName'] - @values.delete 'ai.device.roleName' if @values.key? 'ai.device.roleName' - else - @values['ai.device.roleName'] = value - end - end - - # Gets the screen_resolution property. - def screen_resolution - @values.fetch('ai.device.screenResolution') { - @values['ai.device.screenResolution'] = nil - } - end - - # Sets the screen_resolution property. - def screen_resolution=(value) - if value == @defaults['ai.device.screenResolution'] - @values.delete 'ai.device.screenResolution' if @values.key? 'ai.device.screenResolution' - else - @values['ai.device.screenResolution'] = value - end - end - - # Gets the type property. - def type - @values.fetch('ai.device.type') { - @values['ai.device.type'] = nil - } - end - - # Sets the type property. - def type=(value) - if value == @defaults['ai.device.type'] - @values.delete 'ai.device.type' if @values.key? 'ai.device.type' - else - @values['ai.device.type'] = value - end - end - - # Gets the machine_name property. - def machine_name - @values.fetch('ai.device.machineName') { - @values['ai.device.machineName'] = nil - } - end - - # Sets the machine_name property. - def machine_name=(value) - if value == @defaults['ai.device.machineName'] - @values.delete 'ai.device.machineName' if @values.key? 'ai.device.machineName' - else - @values['ai.device.machineName'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class Device + include JsonSerializable + + attr_accessor :id, :ip, :language, :locale, :model, :network, :oem_name, + :os, :os_version, :role_instance, :role_name, :screen_resolution, :type, + :machine_name + + attribute_mapping( + id: 'ai.device.id', + ip: 'ai.device.ip', + language: 'ai.device.language', + locale: 'ai.device.locale', + model: 'ai.device.model', + network: 'ai.device.network', + oem_name: 'ai.device.oemName', + os: 'ai.device.os', + os_version: 'ai.device.osVersion', + role_instance: 'ai.device.roleInstance', + role_name: 'ai.device.roleName', + screen_resolution: 'ai.device.screenResolution', + type: 'ai.device.type', + machine_name: 'ai.device.machineName' + ) end end diff --git a/lib/application_insights/channel/contracts/envelope.rb b/lib/application_insights/channel/contracts/envelope.rb index 20aed17..e227dec 100644 --- a/lib/application_insights/channel/contracts/envelope.rb +++ b/lib/application_insights/channel/contracts/envelope.rb @@ -1,266 +1,40 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Envelope. - class Envelope < JsonSerializable - # Initializes a new instance of the Envelope class. - def initialize(options={}) - defaults = { - 'ver' => 1, - 'name' => nil, - 'time' => nil, - 'sampleRate' => 100.0, - 'seq' => nil, - 'iKey' => nil, - 'flags' => nil, - 'deviceId' => nil, - 'os' => nil, - 'osVer' => nil, - 'appId' => nil, - 'appVer' => nil, - 'userId' => nil, - 'tags' => {}, - 'data' => nil - } - values = { - 'ver' => 1, - 'name' => nil, - 'time' => nil, - 'sampleRate' => 100.0 - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values.fetch('ver') { - @values['ver'] = 1 - } - end - - # Sets the ver property. - def ver=(value) - if value == @defaults['ver'] - @values.delete 'ver' if @values.key? 'ver' - else - @values['ver'] = value - end - end - - # Gets the name property. - def name - @values['name'] - end - - # Sets the name property. - def name=(value) - @values['name'] = value - end - - # Gets the time property. - def time - @values['time'] - end - - # Sets the time property. - def time=(value) - @values['time'] = value - end - - # Gets the sample_rate property. - def sample_rate - @values.fetch('sampleRate') { - @values['sampleRate'] = 100.0 - } - end - - # Sets the sample_rate property. - def sample_rate=(value) - if value == @defaults['sampleRate'] - @values.delete 'sampleRate' if @values.key? 'sampleRate' - else - @values['sampleRate'] = value - end - end - - # Gets the seq property. - def seq - @values.fetch('seq') { - @values['seq'] = nil - } - end - - # Sets the seq property. - def seq=(value) - if value == @defaults['seq'] - @values.delete 'seq' if @values.key? 'seq' - else - @values['seq'] = value - end - end - - # Gets the i_key property. - def i_key - @values.fetch('iKey') { - @values['iKey'] = nil - } - end - - # Sets the i_key property. - def i_key=(value) - if value == @defaults['iKey'] - @values.delete 'iKey' if @values.key? 'iKey' - else - @values['iKey'] = value - end - end - - # Gets the flags property. - def flags - @values.fetch('flags') { - @values['flags'] = nil - } - end - - # Sets the flags property. - def flags=(value) - if value == @defaults['flags'] - @values.delete 'flags' if @values.key? 'flags' - else - @values['flags'] = value - end - end - - # Gets the device_id property. - def device_id - @values.fetch('deviceId') { - @values['deviceId'] = nil - } - end - - # Sets the device_id property. - def device_id=(value) - if value == @defaults['deviceId'] - @values.delete 'deviceId' if @values.key? 'deviceId' - else - @values['deviceId'] = value - end - end - - # Gets the os property. - def os - @values.fetch('os') { - @values['os'] = nil - } - end - - # Sets the os property. - def os=(value) - if value == @defaults['os'] - @values.delete 'os' if @values.key? 'os' - else - @values['os'] = value - end - end - - # Gets the os_ver property. - def os_ver - @values.fetch('osVer') { - @values['osVer'] = nil - } - end - - # Sets the os_ver property. - def os_ver=(value) - if value == @defaults['osVer'] - @values.delete 'osVer' if @values.key? 'osVer' - else - @values['osVer'] = value - end - end - - # Gets the app_id property. - def app_id - @values.fetch('appId') { - @values['appId'] = nil - } - end - - # Sets the app_id property. - def app_id=(value) - if value == @defaults['appId'] - @values.delete 'appId' if @values.key? 'appId' - else - @values['appId'] = value - end - end - - # Gets the app_ver property. - def app_ver - @values.fetch('appVer') { - @values['appVer'] = nil - } - end - - # Sets the app_ver property. - def app_ver=(value) - if value == @defaults['appVer'] - @values.delete 'appVer' if @values.key? 'appVer' - else - @values['appVer'] = value - end - end - - # Gets the user_id property. - def user_id - @values.fetch('userId') { - @values['userId'] = nil - } - end - - # Sets the user_id property. - def user_id=(value) - if value == @defaults['userId'] - @values.delete 'userId' if @values.key? 'userId' - else - @values['userId'] = value - end - end - - # Gets the tags property. - def tags - @values.fetch('tags') { - @values['tags'] = {} - } - end - - # Sets the tags property. - def tags=(value) - if value == @defaults['tags'] - @values.delete 'tags' if @values.key? 'tags' - else - @values['tags'] = value - end - end - - # Gets the data property. - def data - @values.fetch('data') { - @values['data'] = nil - } - end - - # Sets the data property. - def data=(value) - if value == @defaults['data'] - @values.delete 'data' if @values.key? 'data' - else - @values['data'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class Envelope + include JsonSerializable + + attr_accessor :ver, :name, :time, :sample_rate, :seq, :i_key, :flags, :device_id, + :os, :os_ver, :app_id, :app_ver, :user_id, :tags, :data + + attribute_mapping( + ver: 'ver', + name: 'name', + time: 'time', + sample_rate: 'sampleRate', + seq: 'seq', + i_key: 'iKey', + flags: 'flags', + device_id: 'deviceId', + os: 'os', + os_ver: 'osVer', + app_id: 'appId', + app_ver: 'appVer', + user_id: 'userId', + tags: 'tags', + data: 'data' + ) + + def ver + @ver ||= 1 + end + + def sample_rate + @sample_rate ||= 100.0 + end + + def tags + @tags ||= {} end end end diff --git a/lib/application_insights/channel/contracts/event_data.rb b/lib/application_insights/channel/contracts/event_data.rb index 9e92032..4bfb161 100644 --- a/lib/application_insights/channel/contracts/event_data.rb +++ b/lib/application_insights/channel/contracts/event_data.rb @@ -1,77 +1,28 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type EventData. - class EventData < JsonSerializable - # Initializes a new instance of the EventData class. - def initialize(options={}) - defaults = { - 'ver' => 2, - 'name' => nil, - 'properties' => {}, - 'measurements' => {} - } - values = { - 'ver' => 2, - 'name' => nil - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values['ver'] - end - - # Sets the ver property. - def ver=(value) - @values['ver'] = value - end - - # Gets the name property. - def name - @values['name'] - end - - # Sets the name property. - def name=(value) - @values['name'] = value - end - - # Gets the properties property. - def properties - @values.fetch('properties') { - @values['properties'] = {} - } - end - - # Sets the properties property. - def properties=(value) - if value == @defaults['properties'] - @values.delete 'properties' if @values.key? 'properties' - else - @values['properties'] = value - end - end - - # Gets the measurements property. - def measurements - @values.fetch('measurements') { - @values['measurements'] = {} - } - end - - # Sets the measurements property. - def measurements=(value) - if value == @defaults['measurements'] - @values.delete 'measurements' if @values.key? 'measurements' - else - @values['measurements'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class EventData + include JsonSerializable + + attr_accessor :ver, :name, :properties, :measurements + + attribute_mapping( + ver: 'ver', + name: 'name', + properties: 'properties', + measurements: 'measurements' + ) + + def ver + @ver ||= 2 + end + + def properties + @properties ||= {} + end + + def measurements + @measurements ||= {} end end end diff --git a/lib/application_insights/channel/contracts/exception_data.rb b/lib/application_insights/channel/contracts/exception_data.rb index b7e3a83..828e1b1 100644 --- a/lib/application_insights/channel/contracts/exception_data.rb +++ b/lib/application_insights/channel/contracts/exception_data.rb @@ -1,140 +1,37 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type ExceptionData. - class ExceptionData < JsonSerializable - # Initializes a new instance of the ExceptionData class. - def initialize(options={}) - defaults = { - 'ver' => 2, - 'handledAt' => nil, - 'exceptions' => [], - 'severityLevel' => nil, - 'problemId' => nil, - 'crashThreadId' => nil, - 'properties' => {}, - 'measurements' => {} - } - values = { - 'ver' => 2, - 'handledAt' => nil, - 'exceptions' => [] - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values['ver'] - end - - # Sets the ver property. - def ver=(value) - @values['ver'] = value - end - - # Gets the handled_at property. - def handled_at - @values['handledAt'] - end - - # Sets the handled_at property. - def handled_at=(value) - @values['handledAt'] = value - end - - # Gets the exceptions property. - def exceptions - @values['exceptions'] - end - - # Sets the exceptions property. - def exceptions=(value) - @values['exceptions'] = value - end - - # Gets the severity_level property. - def severity_level - @values.fetch('severityLevel') { - @values['severityLevel'] = nil - } - end - - # Sets the severity_level property. - def severity_level=(value) - if value == @defaults['severityLevel'] - @values.delete 'severityLevel' if @values.key? 'severityLevel' - else - @values['severityLevel'] = value - end - end - - # Gets the problem_id property. - def problem_id - @values.fetch('problemId') { - @values['problemId'] = nil - } - end - - # Sets the problem_id property. - def problem_id=(value) - if value == @defaults['problemId'] - @values.delete 'problemId' if @values.key? 'problemId' - else - @values['problemId'] = value - end - end - - # Gets the crash_thread_id property. - def crash_thread_id - @values.fetch('crashThreadId') { - @values['crashThreadId'] = nil - } - end - - # Sets the crash_thread_id property. - def crash_thread_id=(value) - if value == @defaults['crashThreadId'] - @values.delete 'crashThreadId' if @values.key? 'crashThreadId' - else - @values['crashThreadId'] = value - end - end - - # Gets the properties property. - def properties - @values.fetch('properties') { - @values['properties'] = {} - } - end - - # Sets the properties property. - def properties=(value) - if value == @defaults['properties'] - @values.delete 'properties' if @values.key? 'properties' - else - @values['properties'] = value - end - end - - # Gets the measurements property. - def measurements - @values.fetch('measurements') { - @values['measurements'] = {} - } - end - - # Sets the measurements property. - def measurements=(value) - if value == @defaults['measurements'] - @values.delete 'measurements' if @values.key? 'measurements' - else - @values['measurements'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class ExceptionData + include JsonSerializable + + attr_accessor :ver, :handled_at, :exceptions, :severity_level, :problem_id, + :crash_thread_id, :properties, :measurements + + attribute_mapping( + ver: 'ver', + handled_at: 'handledAt', + exceptions: 'exceptions', + severity_level: 'severityLevel', + problem_id: 'problemId', + crash_thread_id: 'crashThreadId', + properties: 'properties', + measurements: 'measurements' + ) + + def ver + @ver ||= 2 + end + + def exceptions + @exceptions ||= [] + end + + def properties + @properties ||= {} + end + + def measurements + @measurements ||= {} end end end diff --git a/lib/application_insights/channel/contracts/exception_details.rb b/lib/application_insights/channel/contracts/exception_details.rb index 3be01ab..85bfc62 100644 --- a/lib/application_insights/channel/contracts/exception_details.rb +++ b/lib/application_insights/channel/contracts/exception_details.rb @@ -1,129 +1,28 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type ExceptionDetails. - class ExceptionDetails < JsonSerializable - # Initializes a new instance of the ExceptionDetails class. - def initialize(options={}) - defaults = { - 'id' => nil, - 'outerId' => nil, - 'typeName' => nil, - 'message' => nil, - 'hasFullStack' => true, - 'stack' => nil, - 'parsedStack' => [] - } - values = { - 'typeName' => nil, - 'message' => nil, - 'hasFullStack' => true - } - super defaults, values, options - end - - # Gets the id property. - def id - @values.fetch('id') { - @values['id'] = nil - } - end - - # Sets the id property. - def id=(value) - if value == @defaults['id'] - @values.delete 'id' if @values.key? 'id' - else - @values['id'] = value - end - end - - # Gets the outer_id property. - def outer_id - @values.fetch('outerId') { - @values['outerId'] = nil - } - end - - # Sets the outer_id property. - def outer_id=(value) - if value == @defaults['outerId'] - @values.delete 'outerId' if @values.key? 'outerId' - else - @values['outerId'] = value - end - end - - # Gets the type_name property. - def type_name - @values['typeName'] - end - - # Sets the type_name property. - def type_name=(value) - @values['typeName'] = value - end - - # Gets the message property. - def message - @values['message'] - end - - # Sets the message property. - def message=(value) - @values['message'] = value - end - - # Gets the has_full_stack property. - def has_full_stack - @values.fetch('hasFullStack') { - @values['hasFullStack'] = true - } - end - - # Sets the has_full_stack property. - def has_full_stack=(value) - if value == @defaults['hasFullStack'] - @values.delete 'hasFullStack' if @values.key? 'hasFullStack' - else - @values['hasFullStack'] = value - end - end - - # Gets the stack property. - def stack - @values.fetch('stack') { - @values['stack'] = nil - } - end - - # Sets the stack property. - def stack=(value) - if value == @defaults['stack'] - @values.delete 'stack' if @values.key? 'stack' - else - @values['stack'] = value - end - end - - # Gets the parsed_stack property. - def parsed_stack - @values.fetch('parsedStack') { - @values['parsedStack'] = [] - } - end - - # Sets the parsed_stack property. - def parsed_stack=(value) - if value == @defaults['parsedStack'] - @values.delete 'parsedStack' if @values.key? 'parsedStack' - else - @values['parsedStack'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class ExceptionDetails + include JsonSerializable + + attr_accessor :id, :outer_id, :type_name, :message, :has_full_stack, :stack, + :parsed_stack + + attribute_mapping( + id: 'id', + outer_id: 'outerId', + type_name: 'typeName', + message: 'message', + has_full_stack: 'hasFullStack', + stack: 'stack', + parsed_stack: 'parsedStack' + ) + + def has_full_stack + @has_full_stack.nil? ? true : @has_full_stack + end + + def parsed_stack + @parsed_stack ||= [] end end end diff --git a/lib/application_insights/channel/contracts/internal.rb b/lib/application_insights/channel/contracts/internal.rb index 5284b7d..15b8184 100644 --- a/lib/application_insights/channel/contracts/internal.rb +++ b/lib/application_insights/channel/contracts/internal.rb @@ -1,53 +1,14 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Internal. - class Internal < JsonSerializable - # Initializes a new instance of the Internal class. - def initialize(options={}) - defaults = { - 'ai.internal.sdkVersion' => nil, - 'ai.internal.agentVersion' => nil - } - values = { - } - super defaults, values, options - end - - # Gets the sdk_version property. - def sdk_version - @values.fetch('ai.internal.sdkVersion') { - @values['ai.internal.sdkVersion'] = nil - } - end - - # Sets the sdk_version property. - def sdk_version=(value) - if value == @defaults['ai.internal.sdkVersion'] - @values.delete 'ai.internal.sdkVersion' if @values.key? 'ai.internal.sdkVersion' - else - @values['ai.internal.sdkVersion'] = value - end - end - - # Gets the agent_version property. - def agent_version - @values.fetch('ai.internal.agentVersion') { - @values['ai.internal.agentVersion'] = nil - } - end - - # Sets the agent_version property. - def agent_version=(value) - if value == @defaults['ai.internal.agentVersion'] - @values.delete 'ai.internal.agentVersion' if @values.key? 'ai.internal.agentVersion' - else - @values['ai.internal.agentVersion'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class Internal + include JsonSerializable + + attr_accessor :sdk_version, :agent_version + + attribute_mapping( + sdk_version: 'ai.internal.sdkVersion', + agent_version: 'ai.internal.agentVersion' + ) end end diff --git a/lib/application_insights/channel/contracts/json_serializable.rb b/lib/application_insights/channel/contracts/json_serializable.rb index 4929680..22c1414 100644 --- a/lib/application_insights/channel/contracts/json_serializable.rb +++ b/lib/application_insights/channel/contracts/json_serializable.rb @@ -2,58 +2,58 @@ module ApplicationInsights module Channel - module Contracts - class JsonSerializable - def initialize(defaults, values, options) - @defaults = defaults - @values = values - if options != nil - options.each do |key, value| - self.send key.to_s + '=', value - end + module Contracts + module JsonSerializable + module ClassMethods + attr_reader :json_mappings + + def attribute_mapping(mappings) + @json_mappings = mappings end end + def self.included(klass) + klass.extend JsonSerializable::ClassMethods + end + + def initialize(attributes = {}) + attributes.each { |k, v| send(:"#{k}=", v) } + end + def to_h output = {} - @defaults.each do |key, default| - if @values.key? key - value = @values[key] - value = default if value == nil - elsif default - value = default - else - next - end + klass = self.class - if value.class == Array - value_copy = [] - value.each do |item| - item.respond_to?(:to_h) ? value_copy.push(item.to_h) : value_copy.push(item) - end - output[key] = value_copy if value_copy.length > 0 - elsif value.class == Hash - value_copy = {} - value.each do |item_key, item_value| - (item_value.respond_to? :to_h) ? value_copy[item_key] = item_value.to_h : value_copy[item_key] = item_value - end - output[key] = value_copy if value_copy.length > 0 - elsif value.respond_to? :to_h - value_copy = value.to_h - output[key] = value_copy if value_copy.length > 0 - else - output[key] = value - end + klass.json_mappings.each do |attr, name| + value = visit self.send(attr) + is_empty = value.respond_to?(:empty?) && value.empty? + + output[name] = value unless value.nil? || is_empty end + output end - def to_json(*) - hash = self.to_h - hash.to_json + def to_json(args = {}) + JSON.generate self.to_h, args + end + + private + + def visit(object) + return unless object + + if object.is_a? Array + object.map { |e| visit e } + elsif object.is_a? Hash + Hash[object.map { |k, v| [k, visit(v)] }] + elsif object.respond_to? :to_h + object.to_h + else + object + end end end end end end - diff --git a/lib/application_insights/channel/contracts/location.rb b/lib/application_insights/channel/contracts/location.rb index 085a9a7..4136c86 100644 --- a/lib/application_insights/channel/contracts/location.rb +++ b/lib/application_insights/channel/contracts/location.rb @@ -1,36 +1,13 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Location. - class Location < JsonSerializable - # Initializes a new instance of the Location class. - def initialize(options={}) - defaults = { - 'ai.location.ip' => nil - } - values = { - } - super defaults, values, options - end - - # Gets the ip property. - def ip - @values.fetch('ai.location.ip') { - @values['ai.location.ip'] = nil - } - end - - # Sets the ip property. - def ip=(value) - if value == @defaults['ai.location.ip'] - @values.delete 'ai.location.ip' if @values.key? 'ai.location.ip' - else - @values['ai.location.ip'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class Location + include JsonSerializable + + attr_accessor :ip + + attribute_mapping( + ip: 'ai.location.ip' + ) end end diff --git a/lib/application_insights/channel/contracts/message_data.rb b/lib/application_insights/channel/contracts/message_data.rb index 8255c4e..1340f5b 100644 --- a/lib/application_insights/channel/contracts/message_data.rb +++ b/lib/application_insights/channel/contracts/message_data.rb @@ -1,77 +1,24 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type MessageData. - class MessageData < JsonSerializable - # Initializes a new instance of the MessageData class. - def initialize(options={}) - defaults = { - 'ver' => 2, - 'message' => nil, - 'severityLevel' => nil, - 'properties' => {} - } - values = { - 'ver' => 2, - 'message' => nil - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values['ver'] - end - - # Sets the ver property. - def ver=(value) - @values['ver'] = value - end - - # Gets the message property. - def message - @values['message'] - end - - # Sets the message property. - def message=(value) - @values['message'] = value - end - - # Gets the severity_level property. - def severity_level - @values.fetch('severityLevel') { - @values['severityLevel'] = nil - } - end - - # Sets the severity_level property. - def severity_level=(value) - if value == @defaults['severityLevel'] - @values.delete 'severityLevel' if @values.key? 'severityLevel' - else - @values['severityLevel'] = value - end - end - - # Gets the properties property. - def properties - @values.fetch('properties') { - @values['properties'] = {} - } - end - - # Sets the properties property. - def properties=(value) - if value == @defaults['properties'] - @values.delete 'properties' if @values.key? 'properties' - else - @values['properties'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class MessageData + include JsonSerializable + + attr_accessor :ver, :message, :severity_level, :properties + + attribute_mapping( + ver: 'ver', + message: 'message', + severity_level: 'severityLevel', + properties: 'properties' + ) + + def ver + @ver ||= 2 + end + + def properties + @properties ||= {} end end end diff --git a/lib/application_insights/channel/contracts/metric_data.rb b/lib/application_insights/channel/contracts/metric_data.rb index a6fa31f..bcb5739 100644 --- a/lib/application_insights/channel/contracts/metric_data.rb +++ b/lib/application_insights/channel/contracts/metric_data.rb @@ -1,60 +1,27 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type MetricData. - class MetricData < JsonSerializable - # Initializes a new instance of the MetricData class. - def initialize(options={}) - defaults = { - 'ver' => 2, - 'metrics' => [], - 'properties' => {} - } - values = { - 'ver' => 2, - 'metrics' => [] - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values['ver'] - end - - # Sets the ver property. - def ver=(value) - @values['ver'] = value - end - - # Gets the metrics property. - def metrics - @values['metrics'] - end - - # Sets the metrics property. - def metrics=(value) - @values['metrics'] = value - end - - # Gets the properties property. - def properties - @values.fetch('properties') { - @values['properties'] = {} - } - end - - # Sets the properties property. - def properties=(value) - if value == @defaults['properties'] - @values.delete 'properties' if @values.key? 'properties' - else - @values['properties'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class MetricData + include JsonSerializable + + attr_accessor :ver, :metrics, :properties + + attribute_mapping( + ver: 'ver', + metrics: 'metrics', + properties: 'properties' + ) + + def ver + @ver ||= 2 + end + + def metrics + @metrics ||= [] + end + + def properties + @properties ||= {} end end end diff --git a/lib/application_insights/channel/contracts/operation.rb b/lib/application_insights/channel/contracts/operation.rb index 286be11..29e5d02 100644 --- a/lib/application_insights/channel/contracts/operation.rb +++ b/lib/application_insights/channel/contracts/operation.rb @@ -1,121 +1,18 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Operation. - class Operation < JsonSerializable - # Initializes a new instance of the Operation class. - def initialize(options={}) - defaults = { - 'ai.operation.id' => nil, - 'ai.operation.name' => nil, - 'ai.operation.parentId' => nil, - 'ai.operation.rootId' => nil, - 'ai.operation.syntheticSource' => nil, - 'ai.operation.isSynthetic' => nil - } - values = { - } - super defaults, values, options - end - - # Gets the id property. - def id - @values.fetch('ai.operation.id') { - @values['ai.operation.id'] = nil - } - end - - # Sets the id property. - def id=(value) - if value == @defaults['ai.operation.id'] - @values.delete 'ai.operation.id' if @values.key? 'ai.operation.id' - else - @values['ai.operation.id'] = value - end - end - - # Gets the name property. - def name - @values.fetch('ai.operation.name') { - @values['ai.operation.name'] = nil - } - end - - # Sets the name property. - def name=(value) - if value == @defaults['ai.operation.name'] - @values.delete 'ai.operation.name' if @values.key? 'ai.operation.name' - else - @values['ai.operation.name'] = value - end - end - - # Gets the parent_id property. - def parent_id - @values.fetch('ai.operation.parentId') { - @values['ai.operation.parentId'] = nil - } - end - - # Sets the parent_id property. - def parent_id=(value) - if value == @defaults['ai.operation.parentId'] - @values.delete 'ai.operation.parentId' if @values.key? 'ai.operation.parentId' - else - @values['ai.operation.parentId'] = value - end - end - - # Gets the root_id property. - def root_id - @values.fetch('ai.operation.rootId') { - @values['ai.operation.rootId'] = nil - } - end - - # Sets the root_id property. - def root_id=(value) - if value == @defaults['ai.operation.rootId'] - @values.delete 'ai.operation.rootId' if @values.key? 'ai.operation.rootId' - else - @values['ai.operation.rootId'] = value - end - end - - # Gets the synthetic_source property. - def synthetic_source - @values.fetch('ai.operation.syntheticSource') { - @values['ai.operation.syntheticSource'] = nil - } - end - - # Sets the synthetic_source property. - def synthetic_source=(value) - if value == @defaults['ai.operation.syntheticSource'] - @values.delete 'ai.operation.syntheticSource' if @values.key? 'ai.operation.syntheticSource' - else - @values['ai.operation.syntheticSource'] = value - end - end - - # Gets the is_synthetic property. - def is_synthetic - @values.fetch('ai.operation.isSynthetic') { - @values['ai.operation.isSynthetic'] = nil - } - end - - # Sets the is_synthetic property. - def is_synthetic=(value) - if value == @defaults['ai.operation.isSynthetic'] - @values.delete 'ai.operation.isSynthetic' if @values.key? 'ai.operation.isSynthetic' - else - @values['ai.operation.isSynthetic'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class Operation + include JsonSerializable + + attr_accessor :id, :name, :parent_id, :root_id, :synthetic_source, :is_synthetic + + attribute_mapping( + id: 'ai.operation.id', + name: 'ai.operation.name', + parent_id: 'ai.operation.parentId', + root_id: 'ai.operation.rootId', + synthetic_source: 'ai.operation.syntheticSource', + is_synthetic: 'ai.operation.isSynthetic' + ) end end diff --git a/lib/application_insights/channel/contracts/page_view_data.rb b/lib/application_insights/channel/contracts/page_view_data.rb index a615720..75dfbeb 100644 --- a/lib/application_insights/channel/contracts/page_view_data.rb +++ b/lib/application_insights/channel/contracts/page_view_data.rb @@ -1,111 +1,30 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type PageViewData. - class PageViewData < JsonSerializable - # Initializes a new instance of the PageViewData class. - def initialize(options={}) - defaults = { - 'ver' => 2, - 'url' => nil, - 'name' => nil, - 'duration' => nil, - 'properties' => {}, - 'measurements' => {} - } - values = { - 'ver' => 2, - 'name' => nil - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values['ver'] - end - - # Sets the ver property. - def ver=(value) - @values['ver'] = value - end - - # Gets the url property. - def url - @values.fetch('url') { - @values['url'] = nil - } - end - - # Sets the url property. - def url=(value) - if value == @defaults['url'] - @values.delete 'url' if @values.key? 'url' - else - @values['url'] = value - end - end - - # Gets the name property. - def name - @values['name'] - end - - # Sets the name property. - def name=(value) - @values['name'] = value - end - - # Gets the duration property. - def duration - @values.fetch('duration') { - @values['duration'] = nil - } - end - - # Sets the duration property. - def duration=(value) - if value == @defaults['duration'] - @values.delete 'duration' if @values.key? 'duration' - else - @values['duration'] = value - end - end - - # Gets the properties property. - def properties - @values.fetch('properties') { - @values['properties'] = {} - } - end - - # Sets the properties property. - def properties=(value) - if value == @defaults['properties'] - @values.delete 'properties' if @values.key? 'properties' - else - @values['properties'] = value - end - end - - # Gets the measurements property. - def measurements - @values.fetch('measurements') { - @values['measurements'] = {} - } - end - - # Sets the measurements property. - def measurements=(value) - if value == @defaults['measurements'] - @values.delete 'measurements' if @values.key? 'measurements' - else - @values['measurements'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class PageViewData + include JsonSerializable + + attr_accessor :ver, :url, :name, :duration, :properties, :measurements + + attribute_mapping( + ver: 'ver', + url: 'url', + name: 'name', + duration: 'duration', + properties: 'properties', + measurements: 'measurements' + ) + + def ver + @ver ||= 2 + end + + def properties + @properties ||= {} + end + + def measurements + @measurements ||= {} end end end diff --git a/lib/application_insights/channel/contracts/remote_dependency_data.rb b/lib/application_insights/channel/contracts/remote_dependency_data.rb index ce02537..70e2a6d 100644 --- a/lib/application_insights/channel/contracts/remote_dependency_data.rb +++ b/lib/application_insights/channel/contracts/remote_dependency_data.rb @@ -1,260 +1,56 @@ require_relative 'json_serializable' +require_relative 'data_point_type' +require_relative 'dependency_kind' +require_relative 'dependency_source_type' -module ApplicationInsights - module Channel - module Contracts - require_relative 'data_point_type' - require_relative 'dependency_kind' - require_relative 'dependency_source_type' - # Data contract class for type RemoteDependencyData. - class RemoteDependencyData < JsonSerializable - # Initializes a new instance of the RemoteDependencyData class. - def initialize(options={}) - defaults = { - 'ver' => 2, - 'name' => nil, - 'kind' => DataPointType::MEASUREMENT, - 'value' => nil, - 'count' => nil, - 'min' => nil, - 'max' => nil, - 'stdDev' => nil, - 'dependencyKind' => DependencyKind::OTHER, - 'success' => true, - 'async' => nil, - 'dependencySource' => DependencySourceType::UNDEFINED, - 'commandName' => nil, - 'dependencyTypeName' => nil, - 'properties' => {} - } - values = { - 'ver' => 2, - 'name' => nil, - 'kind' => DataPointType::MEASUREMENT, - 'value' => nil, - 'dependencyKind' => DependencyKind::OTHER, - 'success' => true, - 'dependencySource' => DependencySourceType::UNDEFINED - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values['ver'] - end - - # Sets the ver property. - def ver=(value) - @values['ver'] = value - end - - # Gets the name property. - def name - @values['name'] - end - - # Sets the name property. - def name=(value) - @values['name'] = value - end - - # Gets the kind property. - def kind - @values.fetch('kind') { - @values['kind'] = DataPointType::MEASUREMENT - } - end - - # Sets the kind property. - def kind=(value) - if value == @defaults['kind'] - @values.delete 'kind' if @values.key? 'kind' - else - @values['kind'] = value - end - end - - # Gets the value property. - def value - @values['value'] - end - - # Sets the value property. - def value=(value) - @values['value'] = value - end - - # Gets the count property. - def count - @values.fetch('count') { - @values['count'] = nil - } - end - - # Sets the count property. - def count=(value) - if value == @defaults['count'] - @values.delete 'count' if @values.key? 'count' - else - @values['count'] = value - end - end - - # Gets the min property. - def min - @values.fetch('min') { - @values['min'] = nil - } - end - - # Sets the min property. - def min=(value) - if value == @defaults['min'] - @values.delete 'min' if @values.key? 'min' - else - @values['min'] = value - end - end - - # Gets the max property. - def max - @values.fetch('max') { - @values['max'] = nil - } - end - - # Sets the max property. - def max=(value) - if value == @defaults['max'] - @values.delete 'max' if @values.key? 'max' - else - @values['max'] = value - end - end - - # Gets the std_dev property. - def std_dev - @values.fetch('stdDev') { - @values['stdDev'] = nil - } - end - - # Sets the std_dev property. - def std_dev=(value) - if value == @defaults['stdDev'] - @values.delete 'stdDev' if @values.key? 'stdDev' - else - @values['stdDev'] = value - end - end - - # Gets the dependency_kind property. - def dependency_kind - @values['dependencyKind'] - end - - # Sets the dependency_kind property. - def dependency_kind=(value) - @values['dependencyKind'] = value - end - - # Gets the success property. - def success - @values.fetch('success') { - @values['success'] = true - } - end - - # Sets the success property. - def success=(value) - if value == @defaults['success'] - @values.delete 'success' if @values.key? 'success' - else - @values['success'] = value - end - end - - # Gets the async property. - def async - @values.fetch('async') { - @values['async'] = nil - } - end - - # Sets the async property. - def async=(value) - if value == @defaults['async'] - @values.delete 'async' if @values.key? 'async' - else - @values['async'] = value - end - end - - # Gets the dependency_source property. - def dependency_source - @values.fetch('dependencySource') { - @values['dependencySource'] = DependencySourceType::UNDEFINED - } - end - - # Sets the dependency_source property. - def dependency_source=(value) - if value == @defaults['dependencySource'] - @values.delete 'dependencySource' if @values.key? 'dependencySource' - else - @values['dependencySource'] = value - end - end - - # Gets the command_name property. - def command_name - @values.fetch('commandName') { - @values['commandName'] = nil - } - end - - # Sets the command_name property. - def command_name=(value) - if value == @defaults['commandName'] - @values.delete 'commandName' if @values.key? 'commandName' - else - @values['commandName'] = value - end - end - - # Gets the dependency_type_name property. - def dependency_type_name - @values.fetch('dependencyTypeName') { - @values['dependencyTypeName'] = nil - } - end - - # Sets the dependency_type_name property. - def dependency_type_name=(value) - if value == @defaults['dependencyTypeName'] - @values.delete 'dependencyTypeName' if @values.key? 'dependencyTypeName' - else - @values['dependencyTypeName'] = value - end - end - - # Gets the properties property. - def properties - @values.fetch('properties') { - @values['properties'] = {} - } - end - - # Sets the properties property. - def properties=(value) - if value == @defaults['properties'] - @values.delete 'properties' if @values.key? 'properties' - else - @values['properties'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class RemoteDependencyData + include JsonSerializable + + attr_accessor :ver, :name, :kind, :value, :count, :min, :max, :std_dev, + :dependency_kind, :success, :async, :dependency_source, :command_name, + :dependency_type_name, :properties + + attribute_mapping( + ver: 'ver', + name: 'name', + kind: 'kind', + value: 'value', + count: 'count', + min: 'min', + max: 'max', + std_dev: 'stdDev', + dependency_kind: 'dependencyKind', + success: 'success', + async: 'async', + dependency_source: 'dependencySource', + command_name: 'commandName', + dependency_type_name: 'dependencyTypeName', + properties: 'properties' + ) + + def ver + @ver ||= 2 + end + + def kind + @kind ||= DataPointType::MEASUREMENT + end + + def dependency_kind + @dependency_kind ||= DependencyKind::OTHER + end + + def success + @success.nil? ? true : @success + end + + def dependency_source + @dependency_source ||= DependencySourceType::UNDEFINED + end + + def properties + @properties ||= {} end end end diff --git a/lib/application_insights/channel/contracts/request_data.rb b/lib/application_insights/channel/contracts/request_data.rb index ac0e61f..cf434fa 100644 --- a/lib/application_insights/channel/contracts/request_data.rb +++ b/lib/application_insights/channel/contracts/request_data.rb @@ -1,176 +1,36 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type RequestData. - class RequestData < JsonSerializable - # Initializes a new instance of the RequestData class. - def initialize(options={}) - defaults = { - 'ver' => 2, - 'id' => nil, - 'name' => nil, - 'startTime' => nil, - 'duration' => nil, - 'responseCode' => nil, - 'success' => nil, - 'httpMethod' => nil, - 'url' => nil, - 'properties' => {}, - 'measurements' => {} - } - values = { - 'ver' => 2, - 'id' => nil, - 'startTime' => nil, - 'duration' => nil, - 'responseCode' => nil, - 'success' => nil - } - super defaults, values, options - end - - # Gets the ver property. - def ver - @values['ver'] - end - - # Sets the ver property. - def ver=(value) - @values['ver'] = value - end - - # Gets the id property. - def id - @values['id'] - end - - # Sets the id property. - def id=(value) - @values['id'] = value - end - - # Gets the name property. - def name - @values.fetch('name') { - @values['name'] = nil - } - end - - # Sets the name property. - def name=(value) - if value == @defaults['name'] - @values.delete 'name' if @values.key? 'name' - else - @values['name'] = value - end - end - - # Gets the start_time property. - def start_time - @values['startTime'] - end - - # Sets the start_time property. - def start_time=(value) - @values['startTime'] = value - end - - # Gets the duration property. - def duration - @values['duration'] - end - - # Sets the duration property. - def duration=(value) - @values['duration'] = value - end - - # Gets the response_code property. - def response_code - @values['responseCode'] - end - - # Sets the response_code property. - def response_code=(value) - @values['responseCode'] = value - end - - # Gets the success property. - def success - @values['success'] - end - - # Sets the success property. - def success=(value) - @values['success'] = value - end - - # Gets the http_method property. - def http_method - @values.fetch('httpMethod') { - @values['httpMethod'] = nil - } - end - - # Sets the http_method property. - def http_method=(value) - if value == @defaults['httpMethod'] - @values.delete 'httpMethod' if @values.key? 'httpMethod' - else - @values['httpMethod'] = value - end - end - - # Gets the url property. - def url - @values.fetch('url') { - @values['url'] = nil - } - end - - # Sets the url property. - def url=(value) - if value == @defaults['url'] - @values.delete 'url' if @values.key? 'url' - else - @values['url'] = value - end - end - - # Gets the properties property. - def properties - @values.fetch('properties') { - @values['properties'] = {} - } - end - - # Sets the properties property. - def properties=(value) - if value == @defaults['properties'] - @values.delete 'properties' if @values.key? 'properties' - else - @values['properties'] = value - end - end - - # Gets the measurements property. - def measurements - @values.fetch('measurements') { - @values['measurements'] = {} - } - end - - # Sets the measurements property. - def measurements=(value) - if value == @defaults['measurements'] - @values.delete 'measurements' if @values.key? 'measurements' - else - @values['measurements'] = value - end - end - end +module ApplicationInsights::Channel::Contracts + class RequestData + include JsonSerializable + + attr_accessor :ver, :id, :name, :start_time, :duration, :response_code, + :success, :http_method, :url, :properties, :measurements + + attribute_mapping( + ver: 'ver', + id: 'id', + name: 'name', + start_time: 'startTime', + duration: 'duration', + response_code: 'responseCode', + success: 'success', + http_method: 'httpMethod', + url: 'url', + properties: 'properties', + measurements: 'measurements' + ) + + def ver + @ver ||= 2 + end + + def properties + @properties ||= {} + end + + def measurements + @measurements ||= {} end end end diff --git a/lib/application_insights/channel/contracts/session.rb b/lib/application_insights/channel/contracts/session.rb index 7a2487c..4bf2ab0 100644 --- a/lib/application_insights/channel/contracts/session.rb +++ b/lib/application_insights/channel/contracts/session.rb @@ -1,70 +1,15 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type Session. - class Session < JsonSerializable - # Initializes a new instance of the Session class. - def initialize(options={}) - defaults = { - 'ai.session.id' => nil, - 'ai.session.isFirst' => nil, - 'ai.session.isNew' => nil - } - values = { - } - super defaults, values, options - end - - # Gets the id property. - def id - @values.fetch('ai.session.id') { - @values['ai.session.id'] = nil - } - end - - # Sets the id property. - def id=(value) - if value == @defaults['ai.session.id'] - @values.delete 'ai.session.id' if @values.key? 'ai.session.id' - else - @values['ai.session.id'] = value - end - end - - # Gets the is_first property. - def is_first - @values.fetch('ai.session.isFirst') { - @values['ai.session.isFirst'] = nil - } - end - - # Sets the is_first property. - def is_first=(value) - if value == @defaults['ai.session.isFirst'] - @values.delete 'ai.session.isFirst' if @values.key? 'ai.session.isFirst' - else - @values['ai.session.isFirst'] = value - end - end - - # Gets the is_new property. - def is_new - @values.fetch('ai.session.isNew') { - @values['ai.session.isNew'] = nil - } - end - - # Sets the is_new property. - def is_new=(value) - if value == @defaults['ai.session.isNew'] - @values.delete 'ai.session.isNew' if @values.key? 'ai.session.isNew' - else - @values['ai.session.isNew'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class Session + include JsonSerializable + + attr_accessor :id, :is_first, :is_new + + attribute_mapping( + id: 'ai.session.id', + is_first: 'ai.session.isFirst', + is_new: 'ai.session.isNew' + ) end end diff --git a/lib/application_insights/channel/contracts/severity_level.rb b/lib/application_insights/channel/contracts/severity_level.rb index 81efaac..322a00e 100644 --- a/lib/application_insights/channel/contracts/severity_level.rb +++ b/lib/application_insights/channel/contracts/severity_level.rb @@ -1,25 +1,13 @@ -require_relative 'json_serializable' +module ApplicationInsights::Channel::Contracts + class SeverityLevel + VERBOSE = 0 -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type SeverityLevel. - class SeverityLevel - # Enumeration value VERBOSE. - VERBOSE = 0 - - # Enumeration value INFORMATION. - INFORMATION = 1 - - # Enumeration value WARNING. - WARNING = 2 - - # Enumeration value ERROR. - ERROR = 3 - - # Enumeration value CRITICAL. - CRITICAL = 4 - end - end + INFORMATION = 1 + + WARNING = 2 + + ERROR = 3 + + CRITICAL = 4 end end diff --git a/lib/application_insights/channel/contracts/stack_frame.rb b/lib/application_insights/channel/contracts/stack_frame.rb index 061808a..b4f4b98 100644 --- a/lib/application_insights/channel/contracts/stack_frame.rb +++ b/lib/application_insights/channel/contracts/stack_frame.rb @@ -1,94 +1,17 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type StackFrame. - class StackFrame < JsonSerializable - # Initializes a new instance of the StackFrame class. - def initialize(options={}) - defaults = { - 'level' => nil, - 'method' => nil, - 'assembly' => nil, - 'fileName' => nil, - 'line' => nil - } - values = { - 'level' => nil, - 'method' => nil - } - super defaults, values, options - end - - # Gets the level property. - def level - @values['level'] - end - - # Sets the level property. - def level=(value) - @values['level'] = value - end - - # Gets the method property. - def method - @values['method'] - end - - # Sets the method property. - def method=(value) - @values['method'] = value - end - - # Gets the assembly property. - def assembly - @values.fetch('assembly') { - @values['assembly'] = nil - } - end - - # Sets the assembly property. - def assembly=(value) - if value == @defaults['assembly'] - @values.delete 'assembly' if @values.key? 'assembly' - else - @values['assembly'] = value - end - end - - # Gets the file_name property. - def file_name - @values.fetch('fileName') { - @values['fileName'] = nil - } - end - - # Sets the file_name property. - def file_name=(value) - if value == @defaults['fileName'] - @values.delete 'fileName' if @values.key? 'fileName' - else - @values['fileName'] = value - end - end - - # Gets the line property. - def line - @values.fetch('line') { - @values['line'] = nil - } - end - - # Sets the line property. - def line=(value) - if value == @defaults['line'] - @values.delete 'line' if @values.key? 'line' - else - @values['line'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class StackFrame + include JsonSerializable + + attr_accessor :level, :method, :assembly, :file_name, :line + + attribute_mapping( + level: 'level', + method: 'method', + assembly: 'assembly', + file_name: 'fileName', + line: 'line' + ) end end diff --git a/lib/application_insights/channel/contracts/user.rb b/lib/application_insights/channel/contracts/user.rb index 367b0e5..30ee8d0 100644 --- a/lib/application_insights/channel/contracts/user.rb +++ b/lib/application_insights/channel/contracts/user.rb @@ -1,104 +1,19 @@ require_relative 'json_serializable' -module ApplicationInsights - module Channel - module Contracts - # Data contract class for type User. - class User < JsonSerializable - # Initializes a new instance of the User class. - def initialize(options={}) - defaults = { - 'ai.user.accountAcquisitionDate' => nil, - 'ai.user.accountId' => nil, - 'ai.user.userAgent' => nil, - 'ai.user.id' => nil, - 'ai.user.storeRegion' => nil - } - values = { - } - super defaults, values, options - end - - # Gets the account_acquisition_date property. - def account_acquisition_date - @values.fetch('ai.user.accountAcquisitionDate') { - @values['ai.user.accountAcquisitionDate'] = nil - } - end - - # Sets the account_acquisition_date property. - def account_acquisition_date=(value) - if value == @defaults['ai.user.accountAcquisitionDate'] - @values.delete 'ai.user.accountAcquisitionDate' if @values.key? 'ai.user.accountAcquisitionDate' - else - @values['ai.user.accountAcquisitionDate'] = value - end - end - - # Gets the account_id property. - def account_id - @values.fetch('ai.user.accountId') { - @values['ai.user.accountId'] = nil - } - end - - # Sets the account_id property. - def account_id=(value) - if value == @defaults['ai.user.accountId'] - @values.delete 'ai.user.accountId' if @values.key? 'ai.user.accountId' - else - @values['ai.user.accountId'] = value - end - end - - # Gets the user_agent property. - def user_agent - @values.fetch('ai.user.userAgent') { - @values['ai.user.userAgent'] = nil - } - end - - # Sets the user_agent property. - def user_agent=(value) - if value == @defaults['ai.user.userAgent'] - @values.delete 'ai.user.userAgent' if @values.key? 'ai.user.userAgent' - else - @values['ai.user.userAgent'] = value - end - end - - # Gets the id property. - def id - @values.fetch('ai.user.id') { - @values['ai.user.id'] = nil - } - end - - # Sets the id property. - def id=(value) - if value == @defaults['ai.user.id'] - @values.delete 'ai.user.id' if @values.key? 'ai.user.id' - else - @values['ai.user.id'] = value - end - end - - # Gets the store_region property. - def store_region - @values.fetch('ai.user.storeRegion') { - @values['ai.user.storeRegion'] = nil - } - end - - # Sets the store_region property. - def store_region=(value) - if value == @defaults['ai.user.storeRegion'] - @values.delete 'ai.user.storeRegion' if @values.key? 'ai.user.storeRegion' - else - @values['ai.user.storeRegion'] = value - end - end - end - end +module ApplicationInsights::Channel::Contracts + class User + include JsonSerializable + + attr_accessor :account_acquisition_date, :account_id, :auth_user_id, :user_agent, :id, + :store_region + + attribute_mapping( + account_acquisition_date: 'ai.user.accountAcquisitionDate', + account_id: 'ai.user.accountId', + user_agent: 'ai.user.userAgent', + id: 'ai.user.id', + auth_user_id: 'ai.user.authUserId', + store_region: 'ai.user.storeRegion' + ) end end diff --git a/lib/application_insights/channel/event.rb b/lib/application_insights/channel/event.rb index 094596a..ae61064 100644 --- a/lib/application_insights/channel/event.rb +++ b/lib/application_insights/channel/event.rb @@ -5,8 +5,10 @@ module ApplicationInsights module Channel # An event class that allows simple cross-thread signalling. # - # 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. + # 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' @@ -26,12 +28,14 @@ module ApplicationInsights @signal = false end - # The signal value for this object. Note that the value of this property is not synchronized - # with respect to {#set} and {#clear} meaning that it could return false positives or negatives. + # The signal value for this object. Note that the value of this property is + # not synchronized with respect to {#set} and {#clear} meaning that it + # could return false positives or negatives. # @return [Boolean] the signal value. attr_reader :signal - # Sets the internal flag to true. Calling this method will also cause all waiting threads to awaken. + # Sets the internal flag to true. Calling this method will also cause all + # waiting threads to awaken. def set @mutex.synchronize do @signal = true @@ -46,19 +50,19 @@ module ApplicationInsights end end - # Calling this method will block until the internal flag is set to true. If the flag is set to true before calling - # this method, we will return immediately. If the timeout parameter is specified, the method will unblock after the - # specified number of seconds. + # Calling this method will block until the internal flag is set to true. + # If the flag is set to true before calling this method, we will return + # immediately. If the timeout parameter is specified, the method will + # unblock after the specified number of seconds. # @param [Fixnum] timeout the timeout for the operation in seconds. # @return [Boolean] the value of the internal flag on exit. def wait(timeout=nil) @mutex.synchronize do - if @signal == false - @condition_variable.wait @mutex, (timeout == nil) ? nil : timeout - end - @signal + @condition_variable.wait(@mutex, timeout) unless @signal end + + @signal end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/channel/queue_base.rb b/lib/application_insights/channel/queue_base.rb index c85e7d3..446cb21 100644 --- a/lib/application_insights/channel/queue_base.rb +++ b/lib/application_insights/channel/queue_base.rb @@ -2,12 +2,14 @@ require 'thread' module ApplicationInsights module Channel - # 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}. + # 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 class. - # @param [SenderBase] sender the sender object that will be used in conjunction with this queue. + # @param [SenderBase] sender the sender object that will be used in + # conjunction with this queue. def initialize(sender) @queue = Queue.new @max_queue_length = 500 @@ -15,40 +17,41 @@ module ApplicationInsights @sender.queue = self if sender end - # The maximum number of items that will be held by the queue before the queue will call the {#flush} method. + # 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 - # The sender that is associated with this queue that this queue will use to send data to the service. + # 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 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. + # 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 - end + return unless item @queue.push(item) - if @queue.length >= @max_queue_length - flush - end + + flush if @queue.length >= @max_queue_length end - # 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. + # 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) - rescue ThreadError => _ - return nil - end + return @queue.pop(true) + rescue ThreadError + return nil end - # Flushes the current queue by notifying the {#sender}. This method needs to be overridden by a concrete - # implementations of the queue class. + # 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 @@ -59,4 +62,4 @@ module ApplicationInsights end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/channel/sender_base.rb b/lib/application_insights/channel/sender_base.rb index da7e3a3..c20c74d 100644 --- a/lib/application_insights/channel/sender_base.rb +++ b/lib/application_insights/channel/sender_base.rb @@ -6,13 +6,16 @@ require 'zlib' module ApplicationInsights module Channel - # 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. + # 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 class. - # @param [String] service_endpoint_uri the address of the service to send telemetry data to. + # @param [String] service_endpoint_uri the address of the service to send + # telemetry data to. def initialize(service_endpoint_uri) @service_endpoint_uri = service_endpoint_uri @queue = nil @@ -23,28 +26,31 @@ module ApplicationInsights # @return [String] the service endpoint URI. attr_accessor :service_endpoint_uri - # The queue that this sender is draining. While {SenderBase} doesn't implement any means of doing so, derivations - # of this class do. + # 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 - # 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. + # 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 - # 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] data_to_send an array of {Contracts::Envelope} objects to send to the service. + # 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] data_to_send an array of + # {Contracts::Envelope} objects to send to the service. def send(data_to_send) uri = URI(@service_endpoint_uri) headers = { - 'Accept' => 'application/json', - 'Content-Type' => 'application/json; charset=utf-8', - 'Content-Encoding' => 'gzip' + 'Accept' => 'application/json', + 'Content-Type' => 'application/json; charset=utf-8', + 'Content-Encoding' => 'gzip' } request = Net::HTTP::Post.new(uri.path, headers) - # Use JSON.generate instead of to_json, otherwise it will default to ActiveSupport::JSON.encode for Rails app + + # Use JSON.generate instead of to_json, otherwise it will + # default to ActiveSupport::JSON.encode for Rails app json = JSON.generate(data_to_send) compressed_data = compress(json) request.body = compressed_data @@ -54,7 +60,9 @@ module ApplicationInsights http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE end + response = http.request(request) + http.finish if http.started? end private @@ -66,7 +74,6 @@ module ApplicationInsights w_gz.close wio.string end - end end end diff --git a/lib/application_insights/channel/synchronous_queue.rb b/lib/application_insights/channel/synchronous_queue.rb index 51833ee..13c2281 100644 --- a/lib/application_insights/channel/synchronous_queue.rb +++ b/lib/application_insights/channel/synchronous_queue.rb @@ -2,9 +2,10 @@ require_relative 'queue_base' module ApplicationInsights module Channel - # 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}. + # 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' @@ -13,16 +14,19 @@ module ApplicationInsights # queue.push 1 class SynchronousQueue < QueueBase # Initializes a new instance of the class. - # @param [SenderBase] sender the sender object that will be used in conjunction with this queue. + # @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 by by calling {#sender}'s {SenderBase#send} method. + # Flushes the current queue by by calling {#sender}'s + # {SenderBase#send} method. def flush local_sender = @sender return unless local_sender - while TRUE + + while true # get at most send_buffer_size items and send them data = [] while data.length < local_sender.send_buffer_size @@ -30,10 +34,12 @@ module ApplicationInsights break if not item data.push item end + break if data.length == 0 + local_sender.send(data) end end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/channel/synchronous_sender.rb b/lib/application_insights/channel/synchronous_sender.rb index c5d8ffa..ade2f08 100644 --- a/lib/application_insights/channel/synchronous_sender.rb +++ b/lib/application_insights/channel/synchronous_sender.rb @@ -2,14 +2,16 @@ require_relative 'sender_base' module ApplicationInsights module Channel - # A synchronous sender that works in conjunction with the {SynchronousQueue}. The queue will call {#send} on the - # current instance with the data to send. + # 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 + SERVICE_ENDPOINT_URI = 'https://dc.services.visualstudio.com/v2/track' # 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') + # @param [String] service_endpoint_uri the address of the service to send + # telemetry data to. + def initialize(service_endpoint_uri = SERVICE_ENDPOINT_URI) super service_endpoint_uri end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/channel/telemetry_channel.rb b/lib/application_insights/channel/telemetry_channel.rb index 7474c02..7dc187f 100644 --- a/lib/application_insights/channel/telemetry_channel.rb +++ b/lib/application_insights/channel/telemetry_channel.rb @@ -11,33 +11,40 @@ require_relative '../../application_insights/version' module ApplicationInsights module Channel - # The telemetry channel is responsible for constructing a {Contracts::Envelope} object from the passed in - # data and specified telemetry context. + # 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' + # event = ApplicationInsights::Channel::Contracts::EventData.new name: 'My event' # channel.write event class TelemetryChannel # 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. + # @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 - # 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) + # 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 - # The queue associated with this channel. All {Contracts::Envelope} objects created by this channel will be - # pushed to this queue. + # 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 - # The sender associated with this channel. This instance will be used to transmit telemetry to the service. + # 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 @@ -48,11 +55,12 @@ module ApplicationInsights @queue.flush end - # 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}. + # 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 @@ -81,8 +89,17 @@ module ApplicationInsights :sdk_version => 'rb:' + ApplicationInsights::VERSION } internal_context = Contracts::Internal.new internal_context_attributes - contexts = [ internal_context, context.application, context.device, context.user, context.session, context.location, context.operation ] - contexts.each { |c| hash.merge!(c.to_h) if c } + + [internal_context, + context.application, + context.device, + context.user, + context.session, + context.location, + context.operation].each { |c| hash.merge!(c.to_h) if c } + + hash.delete_if { |k, v| v.nil? } + hash end @@ -99,4 +116,4 @@ module ApplicationInsights end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/channel/telemetry_context.rb b/lib/application_insights/channel/telemetry_context.rb index 5e75dd6..37772f6 100644 --- a/lib/application_insights/channel/telemetry_context.rb +++ b/lib/application_insights/channel/telemetry_context.rb @@ -7,7 +7,9 @@ require_relative 'contracts/location' module ApplicationInsights module Channel - # Represents the 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 @@ -32,37 +34,45 @@ module ApplicationInsights @properties = {} end - # The instrumentation key that is used to identify which Application Insights application this data is for. + # 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 - # The application context. This contains properties of the application you are running. + # The application context. This contains properties of the + # application you are running. # @return [Contracts::Application] the context object. attr_accessor :application - # The device context. This contains properties of the device you are running on. + # The device context. This contains properties of the + # device you are running on. # @return [Contracts::Device] the context object. attr_accessor :device - # The user context. This contains properties of the user you are generating telemetry for. + # The user context. This contains properties of the + # user you are generating telemetry for. # @return [Contracts::User] the context object. attr_accessor :user - # The session context. This contains properties of the session you are generating telemetry for. + # The session context. This contains properties of the + # session you are generating telemetry for. # @return [Contracts::Session] the context object. attr_accessor :session - # The operation context. This contains properties of the operation you are generating telemetry for. + # The operation context. This contains properties of the + # operation you are generating telemetry for. # @return [Contracts::Operation] the context object. attr_accessor :operation - # The location context. This contains properties of the location you are generating telemetry from. + # The location context. This contains properties of the + # location you are generating telemetry from. # @return [Contracts::Location] the context object. attr_accessor :location - # The property context. This contains free-form properties that you can add to your telemetry. + # The property context. This contains free-form properties + # that you can add to your telemetry. # @return [Hash] the context object. attr_accessor :properties end end -end \ No newline at end of file +end diff --git a/lib/application_insights/rack/track_request.rb b/lib/application_insights/rack/track_request.rb index bcc942b..7f18174 100644 --- a/lib/application_insights/rack/track_request.rb +++ b/lib/application_insights/rack/track_request.rb @@ -8,12 +8,13 @@ module ApplicationInsights class TrackRequest # Initializes a new instance of the class. # @param [Object] app the inner rack application. - # @param [String] instrumentation_key to identify which Application Insights application this data is for. - # @param [Fixnum] buffer_size the buffer size and the buffered requests would send to Application Insights - # when buffer is full. - # @param [Fixnum] send_interval the frequency (in seconds) to check buffer and send buffered requests to Application - # Insights if any. - def initialize(app, instrumentation_key, buffer_size=500, send_interval=60) + # @param [String] instrumentation_key to identify which Application Insights + # application this data is for. + # @param [Fixnum] buffer_size the buffer size and the buffered requests would + # send to Application Insights when buffer is full. + # @param [Fixnum] send_interval the frequency (in seconds) to check buffer + # and send buffered requests to Application Insights if any. + def initialize(app, instrumentation_key, buffer_size = 500, send_interval = 60) @app = app @instrumentation_key = instrumentation_key @buffer_size = buffer_size @@ -32,13 +33,14 @@ module ApplicationInsights end stop = Time.now - if !@client + unless @client sender = @sender || Channel::AsynchronousSender.new sender.send_interval = @send_interval queue = Channel::AsynchronousQueue.new sender queue.max_queue_length = @buffer_size channel = Channel::TelemetryChannel.new nil, queue - @client = TelemetryClient.new @instrumentation_key, channel + + @client = TelemetryClient.new @instrumentation_key, channel end request = ::Rack::Request.new env @@ -47,13 +49,14 @@ module ApplicationInsights duration = format_request_duration(stop - start) success = status.to_i < 400 options = { - :name => "#{request.request_method} #{request.path}", - :http_method => request.request_method, - :url => request.url + :name => "#{request.request_method} #{request.path}", + :http_method => request.request_method, + :url => request.url } + @client.track_request id, start_time, duration, status, success, options - if exception != nil + if exception @client.track_exception exception, handled_at: 'Unhandled' raise exception end @@ -81,4 +84,4 @@ module ApplicationInsights end end end -end \ No newline at end of file +end diff --git a/lib/application_insights/telemetry_client.rb b/lib/application_insights/telemetry_client.rb index 844c425..4be228b 100644 --- a/lib/application_insights/telemetry_client.rb +++ b/lib/application_insights/telemetry_client.rb @@ -13,45 +13,50 @@ require_relative 'channel/contracts/request_data' require_relative 'channel/contracts/severity_level' module ApplicationInsights - # The telemetry client used for sending all types of telemetry. It serves as the main entry point for - # interacting with the Application Insights service. + # The telemetry client used for sending all types of telemetry. It serves as + # the main entry point for interacting with the Application Insights service. class TelemetryClient # Initializes a new instance of the class. - # @param [String] instrumentation_key to identify which Application Insights application this data is for. - # @param [Channel::TelemetryChannel] telemetry_channel the optional telemetry channel to be used instead of - # constructing a default one. + # @param [String] instrumentation_key to identify which Application Insights + # application this data is for. + # @param [Channel::TelemetryChannel] telemetry_channel the optional telemetry + # channel to be used instead of constructing a default one. def initialize(instrumentation_key = nil, telemetry_channel = nil) @context = Channel::TelemetryContext.new @context.instrumentation_key = instrumentation_key @channel = telemetry_channel || Channel::TelemetryChannel.new end - # The context associated with this client. All data objects created by this client will be accompanied by - # this value. + # The context associated with this client. All data objects created by this + # client will be accompanied by this value. # @return [Channel::TelemetryContext] the context instance. attr_reader :context - # The channel associated with this telemetry client. All data created by this client will be passed along with - # the {#context} object to {Channel::TelemetryChannel#write} + # The channel associated with this telemetry client. All data created by this + # client will be passed along with the {#context} object to + # {Channel::TelemetryChannel#write} # @return [Channel::TelemetryChannel] the channel instance. attr_reader :channel - # Send information about the page viewed in the application (a web page for instance). + # Send information about the page viewed in the application (a web page for + # instance). # @param [String] name the name of the page that was viewed. # @param [String] url the URL of the page that was viewed. - # @param [Hash] options the options to create the {Channel::Contracts::PageViewData} object. - # @option options [Fixnum] :duration the duration of the page view in milliseconds. (defaults to: 0) - # @option options [Hash] :properties the set of custom properties the client wants attached to this - # data item. (defaults to: {}) - # @option options [Hash] :measurements the set of custom measurements the client wants to attach to - # this data item (defaults to: {}) + # @param [Hash] options the options to create the + # {Channel::Contracts::PageViewData} object. + # @option options [Fixnum] :duration the duration of the page view in + # milliseconds. (defaults to: 0) + # @option options [Hash] :properties the set of custom properties the client + # wants attached to this data item. (defaults to: {}) + # @option options [Hash] :measurements the set of custom measurements the + # client wants to attach to this data item (defaults to: {}) def track_page_view(name, url, options={}) data_attributes = { :name => name || 'Null', :url => url, :duration => options[:duration], - :properties => options.fetch(:properties) { {} }, - :measurements => options.fetch(:measurements) { {} } + :properties => options[:properties] || {}, + :measurements => options[:measurements] || {} } data = Channel::Contracts::PageViewData.new data_attributes self.channel.write(data, self.context) @@ -59,121 +64,127 @@ module ApplicationInsights # Send information about a single exception that occurred in the application. # @param [Exception] exception the exception that the client wants to send. - # @param [Hash] options the options to create the {Channel::Contracts::ExceptionData} object. - # @option options [String] :handled_at the type of exception (defaults to: 'UserCode') - # @option options [Hash] :properties the set of custom properties the client wants attached to this - # data item. (defaults to: {}) - # @option options [Hash] :measurements the set of custom measurements the client wants to attach to - # this data item (defaults to: {}) + # @param [Hash] options the options to create the + # {Channel::Contracts::ExceptionData} object. + # @option options [String] :handled_at the type of exception + # (defaults to: 'UserCode') + # @option options [Hash] :properties the set of custom properties the client + # wants attached to this data item. (defaults to: {}) + # @option options [Hash] :measurements the set of custom measurements the + # client wants to attach to this data item (defaults to: {}) def track_exception(exception, options={}) - if exception.is_a? Exception - parsed_stack = [] - if exception.backtrace - frame_pattern = /^(?.*):(?\d+)(\.|:in `((?.*)'$))/ - counter = 0; - exception.backtrace.each do |frame| - match = frame_pattern.match frame - stack_frame = Channel::Contracts::StackFrame.new - stack_frame.assembly = 'Unknown' - stack_frame.file_name = match['file'] - stack_frame.level = counter - stack_frame.line = match['line'] - stack_frame.method = match['method'] - parsed_stack << stack_frame - counter += 1 - end + return unless exception.is_a? Exception + + parsed_stack = [] + if exception.backtrace + frame_pattern = /^(?.*):(?\d+)(\.|:in `((?.*)'$))/ + + exception.backtrace.each_with_index do |frame, counter| + match = frame_pattern.match frame + stack_frame = Channel::Contracts::StackFrame.new( + :assembly => 'Unknown', + :file_name => match['file'], + :level => counter, + :line => match['line'], + :method => match['method'] + ) + + parsed_stack << stack_frame end - - details_attributes = { - :id => 1, - :outer_id => 0, - :type_name => exception.class.name, - :message => exception.message, - :has_full_stack => exception.backtrace != nil, - :stack => (exception.backtrace.join("\n") if exception.backtrace), - :parsed_stack => parsed_stack - } - details = Channel::Contracts::ExceptionDetails.new details_attributes - - data_attributes = { - :handled_at => options.fetch(:handled_at,'UserCode'), - :exceptions => [ details ], - :properties => options.fetch(:properties) { {} }, - :measurements => options.fetch(:measurements) { {} } - } - data = Channel::Contracts::ExceptionData.new data_attributes - self.channel.write(data, self.context) end - end - # Send information about a single event that has occurred in the context of the application. - # @param [String] name the data to associate to this event. - # @param [Hash] options the options to create the {Channel::Contracts::EventData} object. - # @option options [Hash] :properties the set of custom properties the client wants attached to this - # data item. (defaults to: {}) - # @option options [Hash] :measurements the set of custom measurements the client wants to attach to - # this data item (defaults to: {}) - def track_event(name, options={}) - data_attributes = { - :name => name || 'Null', - :properties => options.fetch(:properties) { {} }, - :measurements => options.fetch(:measurements) { {} } - } - data = Channel::Contracts::EventData.new data_attributes + details = Channel::Contracts::ExceptionDetails.new( + :id => 1, + :outer_id => 0, + :type_name => exception.class.name, + :message => exception.message, + :has_full_stack => exception.backtrace != nil, + :stack => (exception.backtrace.join("\n") if exception.backtrace), + :parsed_stack => parsed_stack + ) + + data = Channel::Contracts::ExceptionData.new( + :handled_at => options.fetch(:handled_at, 'UserCode'), + :exceptions => [details], + :properties => options[:properties] || {}, + :measurements => options[:measurements] || {} + ) + self.channel.write(data, self.context) end - # Send information about a single metric data point that was captured for the application. + # Send information about a single event that has occurred in the context of + # the application. + # @param [String] name the data to associate to this event. + # @param [Hash] options the options to create the + # {Channel::Contracts::EventData} object. + # @option options [Hash] :properties the set of custom properties the client + # wants attached to this data item. (defaults to: {}) + # @option options [Hash] :measurements the set of custom measurements the + # client wants to attach to this data item (defaults to: {}) + def track_event(name, options={}) + data = Channel::Contracts::EventData.new( + :name => name || 'Null', + :properties => options[:properties] || {}, + :measurements => options[:measurements] || {} + ) + + self.channel.write(data, self.context) + end + + # Send information about a single metric data point that was captured for + # the application. # @param [String] name the name of the metric that was captured. # @param [Fixnum] value the value of the metric that was captured. - # @param [Hash] options the options to create the {Channel::Contracts::MetricData} object. - # @option options [Channel::Contracts::DataPointType] :type the type of the metric (defaults to: - # {Channel::Contracts::DataPointType::AGGREGATION}) - # @option options [Fixnum] :count the number of metrics that were aggregated into this data point - # (defaults to: 0) - # @option options [Fixnum] :min the minimum of all metrics collected that were aggregated into this - # data point (defaults to: 0) - # @option options [Fixnum] :max the maximum of all metrics collected that were aggregated into this - # data point (defaults to: 0) - # @option options [Fixnum] :std_dev the standard deviation of all metrics collected that were aggregated + # @param [Hash] options the options to create the + # {Channel::Contracts::MetricData} object. + # @option options [Channel::Contracts::DataPointType] :type the type of the + # metric (defaults to: {Channel::Contracts::DataPointType::AGGREGATION}) + # @option options [Fixnum] :count the number of metrics that were aggregated # into this data point (defaults to: 0) - # @option options [Hash] :properties the set of custom properties the client wants attached to this - # data item. (defaults to: {}) - # @option options [Hash] :measurements the set of custom measurements the client wants to attach to - # this data item (defaults to: {}) + # @option options [Fixnum] :min the minimum of all metrics collected that + # were aggregated into this data point (defaults to: 0) + # @option options [Fixnum] :max the maximum of all metrics collected that + # were aggregated into this data point (defaults to: 0) + # @option options [Fixnum] :std_dev the standard deviation of all metrics + # collected that were aggregated into this data point (defaults to: 0) + # @option options [Hash] :properties the set of custom properties the client + # wants attached to this data item. (defaults to: {}) + # @option options [Hash] :measurements the set of custom measurements the + # client wants to attach to this data item (defaults to: {}) def track_metric(name, value, options={}) - data_point_attributes = { + data_point = Channel::Contracts::DataPoint.new( :name => name || 'Null', :value => value || 0, - :kind => options.fetch(:type) { Channel::Contracts::DataPointType::AGGREGATION }, + :kind => options[:type] || Channel::Contracts::DataPointType::AGGREGATION, :count => options[:count], :min => options[:min], :max => options[:max], :std_dev => options[:std_dev] - } - data_point = Channel::Contracts::DataPoint.new data_point_attributes + ) + + data = Channel::Contracts::MetricData.new( + :metrics => [data_point], + :properties => options[:properties] || {} + ) - data_attributes = { - :metrics => [ data_point ], - :properties => options.fetch(:properties) { {} } - } - data = Channel::Contracts::MetricData.new data_attributes self.channel.write(data, self.context) end # Sends a single trace statement. # @param [String] name the trace statement. # @param [Channel::Contracts::SeverityLevel] severity_level the severity level. - # @param [Hash] options the options to create the {Channel::Contracts::EventData} object. - # @option options [Hash] :properties the set of custom properties the client wants attached to this - # data item. (defaults to: {}) - def track_trace(name, severity_level = Channel::Contracts::SeverityLevel::INFORMATION, options={}) - data_attributes = { - :message => name || 'Null', - :severity_level => severity_level || Channel::Contracts::SeverityLevel::INFORMATION, - :properties => options.fetch(:properties) { {} } - } - data = Channel::Contracts::MessageData.new data_attributes + # @param [Hash] options the options to create the + # {Channel::Contracts::EventData} object. + # @option options [Hash] :properties the set of custom properties the client + # wants attached to this data item. (defaults to: {}) + def track_trace(name, severity_level = nil, options={}) + data = Channel::Contracts::MessageData.new( + :message => name || 'Null', + :severity_level => severity_level || Channel::Contracts::SeverityLevel::INFORMATION, + :properties => options[:properties] || {} + ) + self.channel.write(data, self.context) end @@ -183,33 +194,34 @@ module ApplicationInsights # @param [String] duration the duration to process the request. # @param [String] response_code the response code of the request. # @param [Boolean] success indicates whether the request succeeds or not. - # @param [Hash] options the options to create the {Channel::Contracts::RequestData} object. + # @param [Hash] options the options to create the + # {Channel::Contracts::RequestData} object. # @option options [String] :name the name of the request. # @option options [String] :http_method the http method used for the request. # @option options [String] :url the url of the request. - # @option options [Hash] :properties the set of custom properties the client wants attached to this - # data item. (defaults to: {}) - # @option options [Hash] :measurements the set of custom measurements the client wants to attach to - # this data item (defaults to: {}) + # @option options [Hash] :properties the set of custom properties the client + # wants attached to this data item. (defaults to: {}) + # @option options [Hash] :measurements the set of custom measurements the + # client wants to attach to this data item (defaults to: {}) def track_request(id, start_time, duration, response_code, success, options={}) - data_attributes = { - :id => id || 'Null', - :start_time => start_time || Time.now.iso8601(7), - :duration => duration || '0:00:00:00.0000000', - :response_code => response_code || 200, - :success => success = nil ? true : success, - :name => options[:name], - :http_method => options[:http_method], - :url => options[:url], - :properties => options.fetch(:properties) { {} }, - :measurements => options.fetch(:measurements) { {} } - } - data = Channel::Contracts::RequestData.new data_attributes + data = Channel::Contracts::RequestData.new( + :id => id || 'Null', + :start_time => start_time || Time.now.iso8601(7), + :duration => duration || '0:00:00:00.0000000', + :response_code => response_code || 200, + :success => success = nil ? true : success, + :name => options[:name], + :http_method => options[:http_method], + :url => options[:url], + :properties => options[:properties] || {}, + :measurements => options[:measurements] || {} + ) + self.channel.write(data, self.context) end - # Flushes data in the queue. Data in the queue will be sent either immediately irrespective of what sender is - # being used. + # Flushes data in the queue. Data in the queue will be sent either immediately + # irrespective of what sender is being used. def flush self.channel.flush end diff --git a/lib/application_insights/unhandled_exception.rb b/lib/application_insights/unhandled_exception.rb index 2fec530..aa87b6f 100644 --- a/lib/application_insights/unhandled_exception.rb +++ b/lib/application_insights/unhandled_exception.rb @@ -10,7 +10,8 @@ module ApplicationInsights @sender = nil # Auto collects unhandled exception and send to the Application Insights service. - # @param (string) instrumentation_key used to identify which Application Insights application this data is for. + # @param (string) instrumentation_key used to identify which Application + # Insights application this data is for. # @example # require 'application_insights' # ApplicationInsights::UnhandledException.collect('') @@ -18,13 +19,15 @@ module ApplicationInsights def self.collect(instrumentation_key) at_exit do # Avoid sending exception more than once if this method got invoked multiple times - send(instrumentation_key) if !@sender + send(instrumentation_key) unless @sender end end # @api private - # Send the last raised exception to the Application Insights service if telemetry_sender is not customized. - # @param (string) instrumentation_key used to identify which Application Insights application this data is for. + # Send the last raised exception to the Application Insights service if + # telemetry_sender is not customized. + # @param (string) instrumentation_key used to identify which Application + # Insights application this data is for. # @param (SenderBase) telemetry_sender used to send the last raised exception. def self.send(instrumentation_key, telemetry_sender = nil) if $! && !$!.is_a?(SystemExit) && !$!.is_a?(SignalException) @@ -42,6 +45,5 @@ module ApplicationInsights client.flush end end - end -end \ No newline at end of file +end diff --git a/test/application_insights.rb b/test/application_insights.rb index d72049e..65d6efb 100644 --- a/test/application_insights.rb +++ b/test/application_insights.rb @@ -6,4 +6,3 @@ Find.find test do |path| require path end end - diff --git a/test/application_insights/channel/contracts/test_application.rb b/test/application_insights/channel/contracts/test_application.rb index 7fbfb54..32e8f0b 100644 --- a/test/application_insights/channel/contracts/test_application.rb +++ b/test/application_insights/channel/contracts/test_application.rb @@ -8,7 +8,7 @@ class TestApplication < Test::Unit::TestCase item = Contracts::Application.new assert_not_nil item end - + def test_ver_works_as_expected expected = 'Test string' item = Contracts::Application.new @@ -20,7 +20,7 @@ class TestApplication < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_build_works_as_expected expected = 'Test string' item = Contracts::Application.new @@ -32,7 +32,7 @@ class TestApplication < Test::Unit::TestCase actual = item.build assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Application.new item.ver = 'Test string' diff --git a/test/application_insights/channel/contracts/test_data.rb b/test/application_insights/channel/contracts/test_data.rb index 9435ba5..6902276 100644 --- a/test/application_insights/channel/contracts/test_data.rb +++ b/test/application_insights/channel/contracts/test_data.rb @@ -8,7 +8,7 @@ class TestData < Test::Unit::TestCase item = Contracts::Data.new assert_not_nil item end - + def test_base_type_works_as_expected expected = 'Test string' item = Contracts::Data.new @@ -20,7 +20,7 @@ class TestData < Test::Unit::TestCase actual = item.base_type assert_equal expected, actual end - + def test_base_data_works_as_expected expected = { 'key' => 'value' } item = Contracts::Data.new @@ -32,7 +32,7 @@ class TestData < Test::Unit::TestCase actual = item.base_data assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Data.new item.base_type = 'Test string' diff --git a/test/application_insights/channel/contracts/test_data_point.rb b/test/application_insights/channel/contracts/test_data_point.rb index ce61523..f99fbe3 100644 --- a/test/application_insights/channel/contracts/test_data_point.rb +++ b/test/application_insights/channel/contracts/test_data_point.rb @@ -8,7 +8,7 @@ class TestDataPoint < Test::Unit::TestCase item = Contracts::DataPoint.new assert_not_nil item end - + def test_name_works_as_expected expected = 'Test string' item = Contracts::DataPoint.new @@ -20,7 +20,7 @@ class TestDataPoint < Test::Unit::TestCase actual = item.name assert_equal expected, actual end - + def test_kind_works_as_expected expected = 5 item = Contracts::DataPoint.new @@ -32,7 +32,7 @@ class TestDataPoint < Test::Unit::TestCase actual = item.kind assert_equal expected, actual end - + def test_value_works_as_expected expected = 1.5 item = Contracts::DataPoint.new @@ -44,7 +44,7 @@ class TestDataPoint < Test::Unit::TestCase actual = item.value assert_equal expected, actual end - + def test_count_works_as_expected expected = 42 item = Contracts::DataPoint.new @@ -56,7 +56,7 @@ class TestDataPoint < Test::Unit::TestCase actual = item.count assert_equal expected, actual end - + def test_min_works_as_expected expected = 1.5 item = Contracts::DataPoint.new @@ -68,7 +68,7 @@ class TestDataPoint < Test::Unit::TestCase actual = item.min assert_equal expected, actual end - + def test_max_works_as_expected expected = 1.5 item = Contracts::DataPoint.new @@ -80,7 +80,7 @@ class TestDataPoint < Test::Unit::TestCase actual = item.max assert_equal expected, actual end - + def test_std_dev_works_as_expected expected = 1.5 item = Contracts::DataPoint.new @@ -92,7 +92,7 @@ class TestDataPoint < Test::Unit::TestCase actual = item.std_dev assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::DataPoint.new item.name = 'Test string' diff --git a/test/application_insights/channel/contracts/test_device.rb b/test/application_insights/channel/contracts/test_device.rb index 0919dc8..6a2cbcc 100644 --- a/test/application_insights/channel/contracts/test_device.rb +++ b/test/application_insights/channel/contracts/test_device.rb @@ -8,7 +8,7 @@ class TestDevice < Test::Unit::TestCase item = Contracts::Device.new assert_not_nil item end - + def test_id_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -20,7 +20,7 @@ class TestDevice < Test::Unit::TestCase actual = item.id assert_equal expected, actual end - + def test_ip_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -32,7 +32,7 @@ class TestDevice < Test::Unit::TestCase actual = item.ip assert_equal expected, actual end - + def test_language_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -44,7 +44,7 @@ class TestDevice < Test::Unit::TestCase actual = item.language assert_equal expected, actual end - + def test_locale_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -56,7 +56,7 @@ class TestDevice < Test::Unit::TestCase actual = item.locale assert_equal expected, actual end - + def test_model_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -68,7 +68,7 @@ class TestDevice < Test::Unit::TestCase actual = item.model assert_equal expected, actual end - + def test_network_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -80,7 +80,7 @@ class TestDevice < Test::Unit::TestCase actual = item.network assert_equal expected, actual end - + def test_oem_name_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -92,7 +92,7 @@ class TestDevice < Test::Unit::TestCase actual = item.oem_name assert_equal expected, actual end - + def test_os_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -104,7 +104,7 @@ class TestDevice < Test::Unit::TestCase actual = item.os assert_equal expected, actual end - + def test_os_version_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -116,7 +116,7 @@ class TestDevice < Test::Unit::TestCase actual = item.os_version assert_equal expected, actual end - + def test_role_instance_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -128,7 +128,7 @@ class TestDevice < Test::Unit::TestCase actual = item.role_instance assert_equal expected, actual end - + def test_role_name_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -140,7 +140,7 @@ class TestDevice < Test::Unit::TestCase actual = item.role_name assert_equal expected, actual end - + def test_screen_resolution_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -152,7 +152,7 @@ class TestDevice < Test::Unit::TestCase actual = item.screen_resolution assert_equal expected, actual end - + def test_type_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -164,7 +164,7 @@ class TestDevice < Test::Unit::TestCase actual = item.type assert_equal expected, actual end - + def test_machine_name_works_as_expected expected = 'Test string' item = Contracts::Device.new @@ -176,7 +176,7 @@ class TestDevice < Test::Unit::TestCase actual = item.machine_name assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Device.new item.id = 'Test string' diff --git a/test/application_insights/channel/contracts/test_envelope.rb b/test/application_insights/channel/contracts/test_envelope.rb index 5d10357..29caa1a 100644 --- a/test/application_insights/channel/contracts/test_envelope.rb +++ b/test/application_insights/channel/contracts/test_envelope.rb @@ -8,7 +8,7 @@ class TestEnvelope < Test::Unit::TestCase item = Contracts::Envelope.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::Envelope.new @@ -20,7 +20,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_name_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -32,7 +32,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.name assert_equal expected, actual end - + def test_time_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -44,7 +44,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.time assert_equal expected, actual end - + def test_sample_rate_works_as_expected expected = 1.5 item = Contracts::Envelope.new @@ -56,7 +56,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.sample_rate assert_equal expected, actual end - + def test_seq_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -68,7 +68,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.seq assert_equal expected, actual end - + def test_i_key_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -80,7 +80,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.i_key assert_equal expected, actual end - + def test_flags_works_as_expected expected = 42 item = Contracts::Envelope.new @@ -92,7 +92,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.flags assert_equal expected, actual end - + def test_device_id_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -104,7 +104,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.device_id assert_equal expected, actual end - + def test_os_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -116,7 +116,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.os assert_equal expected, actual end - + def test_os_ver_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -128,7 +128,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.os_ver assert_equal expected, actual end - + def test_app_id_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -140,7 +140,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.app_id assert_equal expected, actual end - + def test_app_ver_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -152,7 +152,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.app_ver assert_equal expected, actual end - + def test_user_id_works_as_expected expected = 'Test string' item = Contracts::Envelope.new @@ -164,13 +164,13 @@ class TestEnvelope < Test::Unit::TestCase actual = item.user_id assert_equal expected, actual end - + def test_tags_works_as_expected item = Contracts::Envelope.new actual = item.tags assert_not_nil actual end - + def test_data_works_as_expected expected = { 'key' => 'value' } item = Contracts::Envelope.new @@ -182,7 +182,7 @@ class TestEnvelope < Test::Unit::TestCase actual = item.data assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Envelope.new item.ver = 42 diff --git a/test/application_insights/channel/contracts/test_event_data.rb b/test/application_insights/channel/contracts/test_event_data.rb index e5c26df..ef16996 100644 --- a/test/application_insights/channel/contracts/test_event_data.rb +++ b/test/application_insights/channel/contracts/test_event_data.rb @@ -8,7 +8,7 @@ class TestEventData < Test::Unit::TestCase item = Contracts::EventData.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::EventData.new @@ -20,7 +20,7 @@ class TestEventData < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_name_works_as_expected expected = 'Test string' item = Contracts::EventData.new @@ -32,19 +32,19 @@ class TestEventData < Test::Unit::TestCase actual = item.name assert_equal expected, actual end - + def test_properties_works_as_expected item = Contracts::EventData.new actual = item.properties assert_not_nil actual end - + def test_measurements_works_as_expected item = Contracts::EventData.new actual = item.measurements assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::EventData.new item.ver = 42 diff --git a/test/application_insights/channel/contracts/test_exception_data.rb b/test/application_insights/channel/contracts/test_exception_data.rb index c389834..1a78777 100644 --- a/test/application_insights/channel/contracts/test_exception_data.rb +++ b/test/application_insights/channel/contracts/test_exception_data.rb @@ -8,7 +8,7 @@ class TestExceptionData < Test::Unit::TestCase item = Contracts::ExceptionData.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::ExceptionData.new @@ -20,7 +20,7 @@ class TestExceptionData < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_handled_at_works_as_expected expected = 'Test string' item = Contracts::ExceptionData.new @@ -32,13 +32,13 @@ class TestExceptionData < Test::Unit::TestCase actual = item.handled_at assert_equal expected, actual end - + def test_exceptions_works_as_expected item = Contracts::ExceptionData.new actual = item.exceptions assert_not_nil actual end - + def test_severity_level_works_as_expected expected = 5 item = Contracts::ExceptionData.new @@ -50,7 +50,7 @@ class TestExceptionData < Test::Unit::TestCase actual = item.severity_level assert_equal expected, actual end - + def test_problem_id_works_as_expected expected = 'Test string' item = Contracts::ExceptionData.new @@ -62,7 +62,7 @@ class TestExceptionData < Test::Unit::TestCase actual = item.problem_id assert_equal expected, actual end - + def test_crash_thread_id_works_as_expected expected = 42 item = Contracts::ExceptionData.new @@ -74,19 +74,19 @@ class TestExceptionData < Test::Unit::TestCase actual = item.crash_thread_id assert_equal expected, actual end - + def test_properties_works_as_expected item = Contracts::ExceptionData.new actual = item.properties assert_not_nil actual end - + def test_measurements_works_as_expected item = Contracts::ExceptionData.new actual = item.measurements assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::ExceptionData.new item.ver = 42 @@ -94,7 +94,7 @@ class TestExceptionData < Test::Unit::TestCase [ { 'key' => 'value' } ].each do |value| item.exceptions.push value end - + item.severity_level = 5 item.problem_id = 'Test string' item.crash_thread_id = 42 diff --git a/test/application_insights/channel/contracts/test_exception_details.rb b/test/application_insights/channel/contracts/test_exception_details.rb index 770b0ae..227fd50 100644 --- a/test/application_insights/channel/contracts/test_exception_details.rb +++ b/test/application_insights/channel/contracts/test_exception_details.rb @@ -8,7 +8,7 @@ class TestExceptionDetails < Test::Unit::TestCase item = Contracts::ExceptionDetails.new assert_not_nil item end - + def test_id_works_as_expected expected = 42 item = Contracts::ExceptionDetails.new @@ -20,7 +20,7 @@ class TestExceptionDetails < Test::Unit::TestCase actual = item.id assert_equal expected, actual end - + def test_outer_id_works_as_expected expected = 42 item = Contracts::ExceptionDetails.new @@ -32,7 +32,7 @@ class TestExceptionDetails < Test::Unit::TestCase actual = item.outer_id assert_equal expected, actual end - + def test_type_name_works_as_expected expected = 'Test string' item = Contracts::ExceptionDetails.new @@ -44,7 +44,7 @@ class TestExceptionDetails < Test::Unit::TestCase actual = item.type_name assert_equal expected, actual end - + def test_message_works_as_expected expected = 'Test string' item = Contracts::ExceptionDetails.new @@ -56,7 +56,7 @@ class TestExceptionDetails < Test::Unit::TestCase actual = item.message assert_equal expected, actual end - + def test_has_full_stack_works_as_expected expected = TRUE item = Contracts::ExceptionDetails.new @@ -68,7 +68,7 @@ class TestExceptionDetails < Test::Unit::TestCase actual = item.has_full_stack assert_equal expected, actual end - + def test_stack_works_as_expected expected = 'Test string' item = Contracts::ExceptionDetails.new @@ -80,13 +80,13 @@ class TestExceptionDetails < Test::Unit::TestCase actual = item.stack assert_equal expected, actual end - + def test_parsed_stack_works_as_expected item = Contracts::ExceptionDetails.new actual = item.parsed_stack assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::ExceptionDetails.new item.id = 42 @@ -98,7 +98,7 @@ class TestExceptionDetails < Test::Unit::TestCase [ { 'key' => 'value' } ].each do |value| item.parsed_stack.push value end - + actual = item.to_json expected = '{"id":42,"outerId":42,"typeName":"Test string","message":"Test string","hasFullStack":true,"stack":"Test string","parsedStack":[{"key":"value"}]}' assert_equal expected, actual diff --git a/test/application_insights/channel/contracts/test_internal.rb b/test/application_insights/channel/contracts/test_internal.rb index 4323b34..cac3ee2 100644 --- a/test/application_insights/channel/contracts/test_internal.rb +++ b/test/application_insights/channel/contracts/test_internal.rb @@ -8,7 +8,7 @@ class TestInternal < Test::Unit::TestCase item = Contracts::Internal.new assert_not_nil item end - + def test_sdk_version_works_as_expected expected = 'Test string' item = Contracts::Internal.new @@ -20,7 +20,7 @@ class TestInternal < Test::Unit::TestCase actual = item.sdk_version assert_equal expected, actual end - + def test_agent_version_works_as_expected expected = 'Test string' item = Contracts::Internal.new @@ -32,7 +32,7 @@ class TestInternal < Test::Unit::TestCase actual = item.agent_version assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Internal.new item.sdk_version = 'Test string' diff --git a/test/application_insights/channel/contracts/test_location.rb b/test/application_insights/channel/contracts/test_location.rb index 24c3751..d30dd58 100644 --- a/test/application_insights/channel/contracts/test_location.rb +++ b/test/application_insights/channel/contracts/test_location.rb @@ -8,7 +8,7 @@ class TestLocation < Test::Unit::TestCase item = Contracts::Location.new assert_not_nil item end - + def test_ip_works_as_expected expected = 'Test string' item = Contracts::Location.new @@ -20,7 +20,7 @@ class TestLocation < Test::Unit::TestCase actual = item.ip assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Location.new item.ip = 'Test string' diff --git a/test/application_insights/channel/contracts/test_message_data.rb b/test/application_insights/channel/contracts/test_message_data.rb index a92f8dc..ac09ebf 100644 --- a/test/application_insights/channel/contracts/test_message_data.rb +++ b/test/application_insights/channel/contracts/test_message_data.rb @@ -8,7 +8,7 @@ class TestMessageData < Test::Unit::TestCase item = Contracts::MessageData.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::MessageData.new @@ -20,7 +20,7 @@ class TestMessageData < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_message_works_as_expected expected = 'Test string' item = Contracts::MessageData.new @@ -32,7 +32,7 @@ class TestMessageData < Test::Unit::TestCase actual = item.message assert_equal expected, actual end - + def test_severity_level_works_as_expected expected = 5 item = Contracts::MessageData.new @@ -44,13 +44,13 @@ class TestMessageData < Test::Unit::TestCase actual = item.severity_level assert_equal expected, actual end - + def test_properties_works_as_expected item = Contracts::MessageData.new actual = item.properties assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::MessageData.new item.ver = 42 diff --git a/test/application_insights/channel/contracts/test_metric_data.rb b/test/application_insights/channel/contracts/test_metric_data.rb index dec17f4..9a2ccd0 100644 --- a/test/application_insights/channel/contracts/test_metric_data.rb +++ b/test/application_insights/channel/contracts/test_metric_data.rb @@ -8,7 +8,7 @@ class TestMetricData < Test::Unit::TestCase item = Contracts::MetricData.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::MetricData.new @@ -20,26 +20,26 @@ class TestMetricData < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_metrics_works_as_expected item = Contracts::MetricData.new actual = item.metrics assert_not_nil actual end - + def test_properties_works_as_expected item = Contracts::MetricData.new actual = item.properties assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::MetricData.new item.ver = 42 [ { 'key' => 'value' } ].each do |value| item.metrics.push value end - + { 'key1' => 'test value 1' , 'key2' => 'test value 2' }.each do |key, value| item.properties[key] = value end diff --git a/test/application_insights/channel/contracts/test_operation.rb b/test/application_insights/channel/contracts/test_operation.rb index fcd4597..4c4b021 100644 --- a/test/application_insights/channel/contracts/test_operation.rb +++ b/test/application_insights/channel/contracts/test_operation.rb @@ -8,7 +8,7 @@ class TestOperation < Test::Unit::TestCase item = Contracts::Operation.new assert_not_nil item end - + def test_id_works_as_expected expected = 'Test string' item = Contracts::Operation.new @@ -20,7 +20,7 @@ class TestOperation < Test::Unit::TestCase actual = item.id assert_equal expected, actual end - + def test_name_works_as_expected expected = 'Test string' item = Contracts::Operation.new @@ -32,7 +32,7 @@ class TestOperation < Test::Unit::TestCase actual = item.name assert_equal expected, actual end - + def test_parent_id_works_as_expected expected = 'Test string' item = Contracts::Operation.new @@ -44,7 +44,7 @@ class TestOperation < Test::Unit::TestCase actual = item.parent_id assert_equal expected, actual end - + def test_root_id_works_as_expected expected = 'Test string' item = Contracts::Operation.new @@ -56,7 +56,7 @@ class TestOperation < Test::Unit::TestCase actual = item.root_id assert_equal expected, actual end - + def test_synthetic_source_works_as_expected expected = 'Test string' item = Contracts::Operation.new @@ -68,7 +68,7 @@ class TestOperation < Test::Unit::TestCase actual = item.synthetic_source assert_equal expected, actual end - + def test_is_synthetic_works_as_expected expected = 'Test string' item = Contracts::Operation.new @@ -80,7 +80,7 @@ class TestOperation < Test::Unit::TestCase actual = item.is_synthetic assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Operation.new item.id = 'Test string' diff --git a/test/application_insights/channel/contracts/test_page_view_data.rb b/test/application_insights/channel/contracts/test_page_view_data.rb index 04e0abf..c960563 100644 --- a/test/application_insights/channel/contracts/test_page_view_data.rb +++ b/test/application_insights/channel/contracts/test_page_view_data.rb @@ -8,7 +8,7 @@ class TestPageViewData < Test::Unit::TestCase item = Contracts::PageViewData.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::PageViewData.new @@ -20,7 +20,7 @@ class TestPageViewData < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_url_works_as_expected expected = 'Test string' item = Contracts::PageViewData.new @@ -32,7 +32,7 @@ class TestPageViewData < Test::Unit::TestCase actual = item.url assert_equal expected, actual end - + def test_name_works_as_expected expected = 'Test string' item = Contracts::PageViewData.new @@ -44,7 +44,7 @@ class TestPageViewData < Test::Unit::TestCase actual = item.name assert_equal expected, actual end - + def test_duration_works_as_expected expected = 'Test string' item = Contracts::PageViewData.new @@ -56,19 +56,19 @@ class TestPageViewData < Test::Unit::TestCase actual = item.duration assert_equal expected, actual end - + def test_properties_works_as_expected item = Contracts::PageViewData.new actual = item.properties assert_not_nil actual end - + def test_measurements_works_as_expected item = Contracts::PageViewData.new actual = item.measurements assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::PageViewData.new item.ver = 42 diff --git a/test/application_insights/channel/contracts/test_remote_dependency_data.rb b/test/application_insights/channel/contracts/test_remote_dependency_data.rb index 03bde9d..4bf39cf 100644 --- a/test/application_insights/channel/contracts/test_remote_dependency_data.rb +++ b/test/application_insights/channel/contracts/test_remote_dependency_data.rb @@ -8,7 +8,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase item = Contracts::RemoteDependencyData.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::RemoteDependencyData.new @@ -20,7 +20,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_name_works_as_expected expected = 'Test string' item = Contracts::RemoteDependencyData.new @@ -32,7 +32,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.name assert_equal expected, actual end - + def test_kind_works_as_expected expected = 5 item = Contracts::RemoteDependencyData.new @@ -44,7 +44,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.kind assert_equal expected, actual end - + def test_value_works_as_expected expected = 1.5 item = Contracts::RemoteDependencyData.new @@ -56,7 +56,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.value assert_equal expected, actual end - + def test_count_works_as_expected expected = 42 item = Contracts::RemoteDependencyData.new @@ -68,7 +68,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.count assert_equal expected, actual end - + def test_min_works_as_expected expected = 1.5 item = Contracts::RemoteDependencyData.new @@ -80,7 +80,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.min assert_equal expected, actual end - + def test_max_works_as_expected expected = 1.5 item = Contracts::RemoteDependencyData.new @@ -92,7 +92,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.max assert_equal expected, actual end - + def test_std_dev_works_as_expected expected = 1.5 item = Contracts::RemoteDependencyData.new @@ -104,7 +104,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.std_dev assert_equal expected, actual end - + def test_dependency_kind_works_as_expected expected = 5 item = Contracts::RemoteDependencyData.new @@ -116,7 +116,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.dependency_kind assert_equal expected, actual end - + def test_success_works_as_expected expected = TRUE item = Contracts::RemoteDependencyData.new @@ -128,7 +128,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.success assert_equal expected, actual end - + def test_async_works_as_expected expected = TRUE item = Contracts::RemoteDependencyData.new @@ -140,7 +140,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.async assert_equal expected, actual end - + def test_dependency_source_works_as_expected expected = 5 item = Contracts::RemoteDependencyData.new @@ -152,7 +152,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.dependency_source assert_equal expected, actual end - + def test_command_name_works_as_expected expected = 'Test string' item = Contracts::RemoteDependencyData.new @@ -164,7 +164,7 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.command_name assert_equal expected, actual end - + def test_dependency_type_name_works_as_expected expected = 'Test string' item = Contracts::RemoteDependencyData.new @@ -176,13 +176,13 @@ class TestRemoteDependencyData < Test::Unit::TestCase actual = item.dependency_type_name assert_equal expected, actual end - + def test_properties_works_as_expected item = Contracts::RemoteDependencyData.new actual = item.properties assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::RemoteDependencyData.new item.ver = 42 diff --git a/test/application_insights/channel/contracts/test_request_data.rb b/test/application_insights/channel/contracts/test_request_data.rb index c3e7ffd..a977923 100644 --- a/test/application_insights/channel/contracts/test_request_data.rb +++ b/test/application_insights/channel/contracts/test_request_data.rb @@ -8,7 +8,7 @@ class TestRequestData < Test::Unit::TestCase item = Contracts::RequestData.new assert_not_nil item end - + def test_ver_works_as_expected expected = 42 item = Contracts::RequestData.new @@ -20,7 +20,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.ver assert_equal expected, actual end - + def test_id_works_as_expected expected = 'Test string' item = Contracts::RequestData.new @@ -32,7 +32,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.id assert_equal expected, actual end - + def test_name_works_as_expected expected = 'Test string' item = Contracts::RequestData.new @@ -44,7 +44,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.name assert_equal expected, actual end - + def test_start_time_works_as_expected expected = 'Test string' item = Contracts::RequestData.new @@ -56,7 +56,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.start_time assert_equal expected, actual end - + def test_duration_works_as_expected expected = 'Test string' item = Contracts::RequestData.new @@ -68,7 +68,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.duration assert_equal expected, actual end - + def test_response_code_works_as_expected expected = 'Test string' item = Contracts::RequestData.new @@ -80,7 +80,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.response_code assert_equal expected, actual end - + def test_success_works_as_expected expected = TRUE item = Contracts::RequestData.new @@ -92,7 +92,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.success assert_equal expected, actual end - + def test_http_method_works_as_expected expected = 'Test string' item = Contracts::RequestData.new @@ -104,7 +104,7 @@ class TestRequestData < Test::Unit::TestCase actual = item.http_method assert_equal expected, actual end - + def test_url_works_as_expected expected = 'Test string' item = Contracts::RequestData.new @@ -116,19 +116,19 @@ class TestRequestData < Test::Unit::TestCase actual = item.url assert_equal expected, actual end - + def test_properties_works_as_expected item = Contracts::RequestData.new actual = item.properties assert_not_nil actual end - + def test_measurements_works_as_expected item = Contracts::RequestData.new actual = item.measurements assert_not_nil actual end - + def test_to_json_works_as_expected item = Contracts::RequestData.new item.ver = 42 diff --git a/test/application_insights/channel/contracts/test_session.rb b/test/application_insights/channel/contracts/test_session.rb index 2257cb8..016b579 100644 --- a/test/application_insights/channel/contracts/test_session.rb +++ b/test/application_insights/channel/contracts/test_session.rb @@ -8,7 +8,7 @@ class TestSession < Test::Unit::TestCase item = Contracts::Session.new assert_not_nil item end - + def test_id_works_as_expected expected = 'Test string' item = Contracts::Session.new @@ -20,7 +20,7 @@ class TestSession < Test::Unit::TestCase actual = item.id assert_equal expected, actual end - + def test_is_first_works_as_expected expected = 'Test string' item = Contracts::Session.new @@ -32,7 +32,7 @@ class TestSession < Test::Unit::TestCase actual = item.is_first assert_equal expected, actual end - + def test_is_new_works_as_expected expected = 'Test string' item = Contracts::Session.new @@ -44,7 +44,7 @@ class TestSession < Test::Unit::TestCase actual = item.is_new assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::Session.new item.id = 'Test string' diff --git a/test/application_insights/channel/contracts/test_stack_frame.rb b/test/application_insights/channel/contracts/test_stack_frame.rb index c7979ad..03a437b 100644 --- a/test/application_insights/channel/contracts/test_stack_frame.rb +++ b/test/application_insights/channel/contracts/test_stack_frame.rb @@ -8,7 +8,7 @@ class TestStackFrame < Test::Unit::TestCase item = Contracts::StackFrame.new assert_not_nil item end - + def test_level_works_as_expected expected = 42 item = Contracts::StackFrame.new @@ -20,7 +20,7 @@ class TestStackFrame < Test::Unit::TestCase actual = item.level assert_equal expected, actual end - + def test_method_works_as_expected expected = 'Test string' item = Contracts::StackFrame.new @@ -32,7 +32,7 @@ class TestStackFrame < Test::Unit::TestCase actual = item.method assert_equal expected, actual end - + def test_assembly_works_as_expected expected = 'Test string' item = Contracts::StackFrame.new @@ -44,7 +44,7 @@ class TestStackFrame < Test::Unit::TestCase actual = item.assembly assert_equal expected, actual end - + def test_file_name_works_as_expected expected = 'Test string' item = Contracts::StackFrame.new @@ -56,7 +56,7 @@ class TestStackFrame < Test::Unit::TestCase actual = item.file_name assert_equal expected, actual end - + def test_line_works_as_expected expected = 42 item = Contracts::StackFrame.new @@ -68,7 +68,7 @@ class TestStackFrame < Test::Unit::TestCase actual = item.line assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::StackFrame.new item.level = 42 diff --git a/test/application_insights/channel/contracts/test_user.rb b/test/application_insights/channel/contracts/test_user.rb index 7ca52fb..745f82e 100644 --- a/test/application_insights/channel/contracts/test_user.rb +++ b/test/application_insights/channel/contracts/test_user.rb @@ -8,7 +8,7 @@ class TestUser < Test::Unit::TestCase item = Contracts::User.new assert_not_nil item end - + def test_account_acquisition_date_works_as_expected expected = 'Test string' item = Contracts::User.new @@ -20,7 +20,7 @@ class TestUser < Test::Unit::TestCase actual = item.account_acquisition_date assert_equal expected, actual end - + def test_account_id_works_as_expected expected = 'Test string' item = Contracts::User.new @@ -32,7 +32,7 @@ class TestUser < Test::Unit::TestCase actual = item.account_id assert_equal expected, actual end - + def test_user_agent_works_as_expected expected = 'Test string' item = Contracts::User.new @@ -44,7 +44,7 @@ class TestUser < Test::Unit::TestCase actual = item.user_agent assert_equal expected, actual end - + def test_id_works_as_expected expected = 'Test string' item = Contracts::User.new @@ -56,7 +56,19 @@ class TestUser < Test::Unit::TestCase actual = item.id assert_equal expected, actual end - + + def test_user_auth_id_as_expected + expected = 'Test string' + item = Contracts::User.new + item.auth_user_id = expected + actual = item.auth_user_id + assert_equal expected, actual + expected = 'Other string' + item.auth_user_id = expected + actual = item.auth_user_id + assert_equal expected, actual + end + def test_store_region_works_as_expected expected = 'Test string' item = Contracts::User.new @@ -68,7 +80,7 @@ class TestUser < Test::Unit::TestCase actual = item.store_region assert_equal expected, actual end - + def test_to_json_works_as_expected item = Contracts::User.new item.account_acquisition_date = 'Test string' @@ -76,8 +88,9 @@ class TestUser < Test::Unit::TestCase item.user_agent = 'Test string' item.id = 'Test string' item.store_region = 'Test string' + item.auth_user_id = 'Test string' actual = item.to_json - expected = '{"ai.user.accountAcquisitionDate":"Test string","ai.user.accountId":"Test string","ai.user.userAgent":"Test string","ai.user.id":"Test string","ai.user.storeRegion":"Test string"}' + expected = '{"ai.user.accountAcquisitionDate":"Test string","ai.user.accountId":"Test string","ai.user.userAgent":"Test string","ai.user.id":"Test string","ai.user.authUserId":"Test string","ai.user.storeRegion":"Test string"}' assert_equal expected, actual end end diff --git a/test/application_insights/channel/test_asynchronous_queue.rb b/test/application_insights/channel/test_asynchronous_queue.rb index 4b8e5ea..aa480ea 100644 --- a/test/application_insights/channel/test_asynchronous_queue.rb +++ b/test/application_insights/channel/test_asynchronous_queue.rb @@ -44,4 +44,4 @@ class TestAsynchronousQueue < Test::Unit::TestCase result = queue.flush_notification.wait assert_equal true, result end -end \ No newline at end of file +end diff --git a/test/application_insights/channel/test_sender_base.rb b/test/application_insights/channel/test_sender_base.rb index 1b12dca..46d370a 100644 --- a/test/application_insights/channel/test_sender_base.rb +++ b/test/application_insights/channel/test_sender_base.rb @@ -14,14 +14,14 @@ class TestSenderBase < Test::Unit::TestCase assert_equal 100, sender.send_buffer_size end - def test_service_endpoint_uri_works_as_expected + def test_service_endpoint_uri sender = SenderBase.new 'http://tempuri.org' - assert_equal 'http://tempuri.org', item.service_endpoint_uri - item.service_endpoint_uri = 'http://live.com' - assert_equal 'http://live.com', item.service_endpoint_uri + assert_equal 'http://tempuri.org', sender.service_endpoint_uri + sender.service_endpoint_uri = 'http://live.com' + assert_equal 'http://live.com', sender.service_endpoint_uri end - def test_service_endpoint_uri_works_as_expected + def test_sender_queue_attribute sender = SenderBase.new 'http://tempuri.org' assert_nil sender.queue temp = Object.new @@ -84,4 +84,4 @@ class TestSenderBase < Test::Unit::TestCase return thread, port end -end \ No newline at end of file +end diff --git a/test/application_insights/channel/test_telemetry_channel.rb b/test/application_insights/channel/test_telemetry_channel.rb index aaaf5b4..8c9edd4 100644 --- a/test/application_insights/channel/test_telemetry_channel.rb +++ b/test/application_insights/channel/test_telemetry_channel.rb @@ -88,9 +88,7 @@ class MockTelemetryChannelQueue < QueueBase @flush_count = 0 end - attr_accessor :flush_count - - attr_accessor :queue + attr_accessor :flush_count, :queue def push(data) @queue.push data @@ -99,4 +97,4 @@ class MockTelemetryChannelQueue < QueueBase def flush @flush_count += 1 end -end \ No newline at end of file +end diff --git a/test/application_insights/mock_sender.rb b/test/application_insights/mock_sender.rb index 70ab143..6215eb5 100644 --- a/test/application_insights/mock_sender.rb +++ b/test/application_insights/mock_sender.rb @@ -34,4 +34,4 @@ class MockAsynchronousSender < AsynchronousSender def send(data) @buffer << data end -end \ No newline at end of file +end diff --git a/test/application_insights/rack/test_track_request.rb b/test/application_insights/rack/test_track_request.rb index 9a4e917..740b70f 100644 --- a/test/application_insights/rack/test_track_request.rb +++ b/test/application_insights/rack/test_track_request.rb @@ -139,4 +139,4 @@ class TestTrackRequest < Test::Unit::TestCase assert_equal 0, match['second'].to_i assert_equal 0, match['fraction'].to_i end -end \ No newline at end of file +end diff --git a/test/application_insights/test_unhandled_exception.rb b/test/application_insights/test_unhandled_exception.rb index dc2aff0..52d9bd2 100644 --- a/test/application_insights/test_unhandled_exception.rb +++ b/test/application_insights/test_unhandled_exception.rb @@ -5,7 +5,6 @@ require_relative '../../lib/application_insights/unhandled_exception' include ApplicationInsights class TestUnhandledException < Test::Unit::TestCase - def test_send sender = MockSynchronousSender.new error = 'Boom!' @@ -15,10 +14,10 @@ class TestUnhandledException < Test::Unit::TestCase rescue UnhandledException.send instrumentation_key, sender end + payload = sender.buffer[0] assert_equal 1, sender.buffer.count - payload = sender.buffer[0] assert_equal instrumentation_key, payload[0].i_key assert_equal 'Unhandled', payload[0].data.base_data.handled_at end -end \ No newline at end of file +end