diff --git a/Ema.indigoPlugin/Contents/Info.plist b/Ema.indigoPlugin/Contents/Info.plist index 76d76b4..a3a0c8c 100644 --- a/Ema.indigoPlugin/Contents/Info.plist +++ b/Ema.indigoPlugin/Contents/Info.plist @@ -3,7 +3,7 @@ PluginVersion - 0.1.0 + 0.1.1 ServerApiVersion 2.0 IwsApiVersion diff --git a/Ema.indigoPlugin/Contents/Server Plugin/Ema.pyc b/Ema.indigoPlugin/Contents/Server Plugin/Ema.pyc index 744bd65..bb9a4c6 100644 Binary files a/Ema.indigoPlugin/Contents/Server Plugin/Ema.pyc and b/Ema.indigoPlugin/Contents/Server Plugin/Ema.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/TelemetryClient.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/TelemetryClient.py new file mode 100644 index 0000000..b9d02cd --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/TelemetryClient.py @@ -0,0 +1,225 @@ +import datetime +import traceback +import sys +import uuid +from applicationinsights import channel + +NULL_CONSTANT_STRING = 'Null' + +class TelemetryClient(object): + """The telemetry client used for sending all types of telemetry. It serves as the main entry point for + interacting with the Application Insights service. + """ + def __init__(self, instrumentation_key, telemetry_channel=None): + """Initializes a new instance of the class. + + Args: + instrumentation_key (str). the instrumentation key to use for this telemetry client.\n + telemetry_channel (:class:`channel.TelemetryChannel`). the optional telemetry channel to be used instead of + constructing a default one. + """ + if instrumentation_key: + if isinstance(instrumentation_key, channel.TelemetryChannel): + telemetry_channel = instrumentation_key + instrumentation_key = None + else: + raise Exception('Instrumentation key was required but not provided') + self._context = channel.TelemetryContext() + self._context.instrumentation_key = instrumentation_key + self._channel = telemetry_channel or channel.TelemetryChannel() + + @property + def context(self): + """The context associated with this client. All data objects created by this client will be accompanied by + this value. + + Returns: + :class:`channel.TelemetryChannel`. the context instance. + """ + return self._context + + @property + def channel(self): + """The channel associated with this telemetry client. All data created by this client will be passed along with + the :func:`context` object to :class:`channel.TelemetryChannel`'s :func:`write`. + + Returns: + :class:`channel.TelemetryChannel`. the channel instance. + """ + return self._channel + + def flush(self): + """Flushes data in the queue. Data in the queue will be sent either immediately irrespective of what sender is + being used. + """ + self._channel.flush() + + def track_pageview(self, name, url, duration=0, properties=None, measurements=None): + """Send information about the page viewed in the application (a web page for instance). + + Args: + name (str). the name of the page that was viewed.\n + url (str). the URL of the page that was viewed.\n + duration (int). the duration of the page view in milliseconds. (defaults to: 0)\n + properties (dict). the set of custom properties the client wants attached to this data item. (defaults to: None)\n + measurements (dict). the set of custom measurements the client wants to attach to this data item. (defaults to: None) + """ + data = channel.contracts.PageViewData() + data.name = name or NULL_CONSTANT_STRING + data.url = url + data.duration = duration + if properties: + data.properties = properties + if measurements: + data.measurements = measurements + + self._channel.write(data, self._context) + + def track_exception(self, type=None, value=None, tb=None, properties=None, measurements=None): + """ Send information about a single exception that occurred in the application. + + Args: + type (Type). the type of the exception that was thrown.\n + value (:class:`Exception`). the exception that the client wants to send.\n + tb (:class:`Traceback`). the traceback information as returned by :func:`sys.exc_info`.\n + properties (dict). the set of custom properties the client wants attached to this data item. (defaults to: None)\n + measurements (dict). the set of custom measurements the client wants to attach to this data item. (defaults to: None) + """ + if not type or not value or not tb: + type, value, tb = sys.exc_info() + + if not type or not value or not tb: + try: + raise Exception(NULL_CONSTANT_STRING) + except: + type, value, tb = sys.exc_info() + + details = channel.contracts.ExceptionDetails() + details.id = 1 + details.outer_id = 0 + details.type_name = type.__name__ + details.message = str(value) + details.has_full_stack = True + counter = 0 + for tb_frame_file, tb_frame_line, tb_frame_function, tb_frame_text in traceback.extract_tb(tb): + frame = channel.contracts.StackFrame() + frame.assembly = 'Unknown' + frame.file_name = tb_frame_file + frame.level = counter + frame.line = tb_frame_line + frame.method = tb_frame_function + details.parsed_stack.append(frame) + counter += 1 + details.parsed_stack.reverse() + + data = channel.contracts.ExceptionData() + data.handled_at = 'UserCode' + data.exceptions.append(details) + if properties: + data.properties = properties + if measurements: + data.measurements = measurements + + self._channel.write(data, self._context) + + def track_event(self, name, properties=None, measurements=None): + """ Send information about a single event that has occurred in the context of the application. + + Args: + name (str). the data to associate to this event.\n + properties (dict). the set of custom properties the client wants attached to this data item. (defaults to: None)\n + measurements (dict). the set of custom measurements the client wants to attach to this data item. (defaults to: None) + """ + data = channel.contracts.EventData() + data.name = name or NULL_CONSTANT_STRING + if properties: + data.properties = properties + if measurements: + data.measurements = measurements + + self._channel.write(data, self._context) + + def track_metric(self, name, value, type=None, count=None, min=None, max=None, std_dev=None, properties=None): + """Send information about a single metric data point that was captured for the application. + + Args: + name (str). the name of the metric that was captured.\n + value (float). the value of the metric that was captured.\n + type (:class:`channel.contracts.DataPointType`). the type of the metric. (defaults to: :func:`channel.contracts.DataPointType.aggregation`)\n + count (int). the number of metrics that were aggregated into this data point. (defaults to: None)\n + min (float). the minimum of all metrics collected that were aggregated into this data point. (defaults to: None)\n + max (float). the maximum of all metrics collected that were aggregated into this data point. (defaults to: None)\n + std_dev (float). the standard deviation of all metrics collected that were aggregated into this data point. (defaults to: None)\n + properties (dict). the set of custom properties the client wants attached to this data item. (defaults to: None) + """ + dataPoint = channel.contracts.DataPoint() + dataPoint.name = name or NULL_CONSTANT_STRING + dataPoint.value = value or 0 + dataPoint.kind = type or channel.contracts.DataPointType.aggregation + dataPoint.count = count + dataPoint.min = min + dataPoint.max = max + dataPoint.std_dev = std_dev + + data = channel.contracts.MetricData() + data.metrics.append(dataPoint) + if properties: + data.properties = properties + + self._channel.write(data, self._context) + + def track_trace(self, name, properties=None): + """Sends a single trace statement. + + Args: + name (str). the trace statement.\n + properties (dict). the set of custom properties the client wants attached to this data item. (defaults to: None) + """ + data = channel.contracts.MessageData() + data.message = name or NULL_CONSTANT_STRING + if properties: + data.properties = properties + + self._channel.write(data, self._context) + + def track_request(self, name, url, success, start_time=None, duration=None, response_code=None, http_method=None, properties=None, measurements=None): + """Sends a single request that was captured for the application. + + Args: + name (str). the name for this request. All requests with the same name will be grouped together.\n + url (str). the actual URL for this request (to show in individual request instances).\n + success (bool). true if the request ended in success, false otherwise.\n + start_time (str). the start time of the request. The value should look the same as the one returned by :func:`datetime.isoformat()` (defaults to: None)\n + duration (int). the number of milliseconds that this request lasted. (defaults to: None)\n + response_code (string). the response code that this request returned. (defaults to: None)\n + http_method (string). the HTTP method that triggered this request. (defaults to: None)\n + properties (dict). the set of custom properties the client wants attached to this data item. (defaults to: None)\n + measurements (dict). the set of custom measurements the client wants to attach to this data item. (defaults to: None) + """ + data = channel.contracts.RequestData() + data.id = str(uuid.uuid4()) + data.name = name + data.start_time = start_time or datetime.datetime.utcnow().isoformat() + 'Z' + + local_duration = duration or 0 + duration_parts = [] + for multiplier in [1000, 60, 60, 24]: + duration_parts.append(local_duration % multiplier) + local_duration //= multiplier + + duration_parts.reverse() + data.duration = '%02d:%02d:%02d.%03d' % tuple(duration_parts) + if local_duration: + data.duration = '%d.%s' % (local_duration, data.duration) + + data.response_code = response_code or '200' + data.success = success + data.http_method = http_method or 'GET' + data.url = url + if properties: + data.properties = properties + if measurements: + data.measurements = measurements + + self.channel.write(data, self._context) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/TelemetryClient.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/TelemetryClient.pyc new file mode 100644 index 0000000..2d022a2 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/TelemetryClient.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/__init__.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/__init__.py new file mode 100644 index 0000000..f7fb598 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/__init__.py @@ -0,0 +1,4 @@ +from .TelemetryClient import TelemetryClient +from . import channel +from . import logging +from . import requests \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/__init__.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/__init__.pyc new file mode 100644 index 0000000..a70afc3 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/__init__.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousQueue.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousQueue.py new file mode 100644 index 0000000..cdd0e9b --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousQueue.py @@ -0,0 +1,44 @@ +from .QueueBase import QueueBase +from threading import Event + +class AsynchronousQueue(QueueBase): + """An asynchronous queue for use in conjunction with the :class:`AsynchronousSender`. The queue + will notify the sender that it needs to pick up items when it reaches :func:`max_queue_length`, or + when the consumer calls :func:`flush` via the :func:`flush_notification` event. + """ + def __init__(self, sender): + """Initializes a new instance of the class. + + Args: + sender (:class:`SenderBase`) the sender object that will be used in conjunction with this queue. + """ + self._flush_notification = Event() + QueueBase.__init__(self, sender) + + @property + def flush_notification(self): + """The flush notification :class:`Event` that the :func:`sender` will use to get notified + that a flush is needed. + + Returns: + :class:`Event`. object that the :func:`sender` can wait on. + """ + return self._flush_notification + + def put(self, item): + """Adds the passed in item object to the queue and notifies the :func:`sender` to start an asynchronous + send operation by calling :func:`start`. + + Args: + item (:class:`contracts.Envelope`) the telemetry envelope object to send to the service. + """ + QueueBase.put(self, item) + if self.sender: + self.sender.start() + + def flush(self): + """Flushes the current queue by notifying the :func:`sender` via the :func:`flush_notification` event. + """ + self._flush_notification.set() + if self.sender: + self.sender.start() diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousQueue.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousQueue.pyc new file mode 100644 index 0000000..212a398 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousQueue.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousSender.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousSender.py new file mode 100644 index 0000000..fc4549e --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousSender.py @@ -0,0 +1,147 @@ +from .SenderBase import SenderBase +from threading import Lock, Thread + +class AsynchronousSender(SenderBase): + """An asynchronous sender that works in conjunction with the :class:`AsynchronousQueue`. The sender object will + start a worker thread that will pull items from the :func:`queue`. The thread will be created when the client + calls :func:`start` and will check for queue items every :func:`send_interval` seconds. The worker thread can + also be forced to check the queue by setting the :func:`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 :func:`send_buffer_size`. + + If no queue items are found for :func:`send_time` seconds, the worker thread will shut down (and :func:`start` will + need to be called again). + """ + def __init__(self, service_endpoint_uri='https://dc.services.visualstudio.com/v2/track'): + """Initializes a new instance of the class. + + Args: + sender (String) service_endpoint_uri the address of the service to send telemetry data to. + """ + self._send_interval = 1.0 + self._send_remaining_time = 0 + self._send_time = 3.0 + self._lock_send_remaining_time = Lock() + SenderBase.__init__(self, service_endpoint_uri) + + @property + def send_interval(self): + """The time span in seconds at which the the worker thread will check the :func:`queue` for items (defaults to: 1.0). + + Args: + value (int) the interval in seconds. + + Returns: + int. the interval in seconds. + """ + return self._send_interval + + @send_interval.setter + def send_interval(self, value): + """The time span in seconds at which the the worker thread will check the :func:`queue` for items (defaults to: 1.0). + + Args: + value (int) the interval in seconds. + + Returns: + int. the interval in seconds. + """ + self._send_interval = value + + @property + def send_time(self): + """The time span in seconds at which the the worker thread will check the :func:`queue` for items (defaults to: 1.0). + + Args: + value (int) the interval in seconds. + + Returns: + int. the interval in seconds. + """ + return self._send_time + + @send_time.setter + def send_time(self, value): + """The time span in seconds at which the the worker thread will check the :func:`queue` for items (defaults to: 1.0). + + Args: + value (int) the interval in seconds. + + Returns: + int. the interval in seconds. + """ + self._send_time = value + + def start(self): + """Starts a new sender thread if none is not already there + """ + with self._lock_send_remaining_time: + if self._send_remaining_time <= 0.0: + local_send_interval = self._send_interval + if self._send_interval < 0.1: + local_send_interval = 0.1 + self._send_remaining_time = self._send_time + if self._send_remaining_time < local_send_interval: + self._send_remaining_time = local_send_interval + thread = Thread(target=self._run) + thread.daemon = True + thread.start() + + def stop(self): + """Gracefully stops the sender thread if one is there. + """ + with self._lock_send_remaining_time: + self._send_remaining_time = 0.0 + + def _run(self): + # save the queue locally + local_queue = self._queue + if not local_queue: + self.stop() + return + + # fix up the send interval (can't be lower than 100ms) + local_send_interval = self._send_interval + if self._send_interval < 0.1: + local_send_interval = 0.1 + local_send_time = self._send_time + if local_send_time < local_send_interval: + local_send_time = local_send_interval + while True: + while True: + # get at most send_buffer_size items from the queue + counter = self._send_buffer_size + data = [] + while counter > 0: + item = local_queue.get() + if not item: + break + data.append(item) + counter -= 1 + + # if we didn't get any items from the queue, we're done here + if len(data) == 0: + break + + # reset the send time + with self._lock_send_remaining_time: + self._send_remaining_time = local_send_time + + # finally send the data + self.send(data) + + # wait at most send_interval (or until we get signalled) + result = local_queue.flush_notification.wait(local_send_interval) + if result: + local_queue.flush_notification.clear() + continue + + # decrement the remaining time + local_remaining_time = 0 + with self._lock_send_remaining_time: + self._send_remaining_time -= local_send_interval + local_remaining_time = self._send_remaining_time + + if local_remaining_time <= 0: + break diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousSender.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousSender.pyc new file mode 100644 index 0000000..6a2b0b1 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/AsynchronousSender.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/QueueBase.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/QueueBase.py new file mode 100644 index 0000000..64c76c7 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/QueueBase.py @@ -0,0 +1,91 @@ +try: + # Python 2.x + from Queue import Queue, Empty +except ImportError: + # Python 3.x + from queue import Queue, Empty + +class QueueBase(object): + """The base class for all types of queues for use in conjunction with an implementation of :class:`SenderBase`. + + The queue will notify the sender that it needs to pick up items when it reaches :func:`max_queue_length`, + or when the consumer calls :func:`flush`. + """ + def __init__(self, sender): + """Initializes a new instance of the class. + + Args: + sender (:class:`SenderBase`) the sender object that will be used in conjunction with this queue. + """ + self._queue = Queue() + self._max_queue_length = 500 + self._sender = sender + if sender: + self._sender.queue = self + + @property + def max_queue_length(self): + """The maximum number of items that will be held by the queue before the queue will call the :func:`flush` + method. + + Args: + value (int). the maximum queue length. The minimum allowed value is 1. + + Returns: + int. the maximum queue size. (defaults to: 500) + """ + return self._max_queue_length + + @max_queue_length.setter + def max_queue_length(self, value): + """The maximum number of items that will be held by the queue before the queue will call the :func:`flush` + method. + + Args: + value (int): the maximum queue length. The minimum allowed value is 1. + + Returns: + int. the maximum queue size. (defaults to: 500) + """ + if value < 1: + value = 1 + self._max_queue_length = value + + @property + def sender(self): + """The sender that is associated with this queue that this queue will use to send data to the service. + + Returns: + :class:`SenderBase`. the sender object. + """ + return self._sender + + def put(self, item): + """Adds the passed in item object to the queue and calls :func:`flush` if the size of the queue is larger + than :func:`max_queue_length`. This method does nothing if the passed in item is None. + + Args: + item (:class:`contracts.Envelope`) item the telemetry envelope object to send to the service. + """ + if not item: + return + self._queue.put(item) + if self._queue.qsize() >= self._max_queue_length: + self.flush() + + def get(self): + """Gets a single item from the queue and returns it. If the queue is empty, this method will return None. + + Returns: + :class:`contracts.Envelope`. a telemetry envelope object or None if the queue is empty. + """ + try: + return self._queue.get_nowait() + except Empty: + return None + + def flush(self): + """Flushes the current queue by notifying the {#sender}. This method needs to be overridden by a concrete + implementations of the queue class. + """ + pass \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/QueueBase.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/QueueBase.pyc new file mode 100644 index 0000000..8495cf2 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/QueueBase.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SenderBase.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SenderBase.py new file mode 100644 index 0000000..c31116e --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SenderBase.py @@ -0,0 +1,130 @@ +import json + +try: + # Python 2.x + import urllib2 as HTTPClient + from urllib2 import HTTPError +except ImportError: + # Python 3.x + import urllib.request as HTTPClient + from urllib.error import HTTPError + +class SenderBase(object): + """The base class for all types of senders for use in conjunction with an implementation of :class:`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 getting at most :func:`send_buffer_size` items. + It will then call :func:`send` using the list of items pulled from the queue. + """ + def __init__(self, service_endpoint_uri): + """Initializes a new instance of the class. + + Args: + service_endpoint_uri (str) the address of the service to send telemetry data to. + """ + self._service_endpoint_uri = service_endpoint_uri + self._queue = None + self._send_buffer_size = 100 + + @property + def service_endpoint_uri(self): + """The HTTP or HTTPS endpoint that this sender will send data to. + + Args: + value (str). the service endpoint URI. + + Returns: + str. the service endpoint URI. + """ + return self._service_endpoint_uri + + @service_endpoint_uri.setter + def service_endpoint_uri(self, value): + """The service endpoint URI where this sender will send data to. + + Args: + value (str). the service endpoint URI. + + Returns: + str. the service endpoint URI. + """ + self._service_endpoint_uri = value + + @property + def queue(self): + """The queue that this sender is draining. While :class:`SenderBase` doesn't implement any means of doing + so, derivations of this class do. + + Args: + value (:class:`QueueBase`). the queue instance that this sender is draining. + + Returns: + :class:`QueueBase`. the queue instance that this sender is draining. + """ + return self._queue + + @queue.setter + def queue(self, value): + """The queue that this sender is draining. While :class:`SenderBase` doesn't implement any means of doing + so, derivations of this class do. + + Args: + value (:class:`QueueBase`). the queue instance that this sender is draining. + + Returns: + :class:`QueueBase`. the queue instance that this sender is draining. + """ + self._queue = value + + @property + def send_buffer_size(self): + """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. + + Args: + value (int). the maximum number of items in a telemetry batch. + + Returns: + int. the maximum number of items in a telemetry batch. + """ + return self._send_buffer_size + + @send_buffer_size.setter + def send_buffer_size(self, value): + """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. + + Args: + value (int). the maximum number of items in a telemetry batch. + + Returns: + int. the maximum number of items in a telemetry batch. + """ + if value < 1: + value = 1 + self._send_buffer_size = value + + def send(self, data_to_send): + """ Immediately sends the data passed in to :func:`service_endpoint_uri`. If the service request fails, the + passed in items are pushed back to the :func:`queue`. + + Args: + data_to_send (Array): an array of :class:`contracts.Envelope` objects to send to the service. + """ + request_payload = json.dumps([ a.write() for a in data_to_send ]) + + request = HTTPClient.Request(self._service_endpoint_uri, bytearray(request_payload, 'utf-8'), { 'Accept': 'application/json', 'Content-Type' : 'application/json; charset=utf-8' }) + try: + response = HTTPClient.urlopen(request) + status_code = response.getcode() + if 200 <= status_code < 300: + return + except HTTPError as e: + if e.getcode() == 400: + return + except Exception as e: + pass + + # Add our unsent data back on to the queue + for data in data_to_send: + self._queue.put(data) \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SenderBase.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SenderBase.pyc new file mode 100644 index 0000000..118f0ec Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SenderBase.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousQueue.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousQueue.py new file mode 100644 index 0000000..427df02 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousQueue.py @@ -0,0 +1,39 @@ +from .QueueBase import QueueBase + +class SynchronousQueue(QueueBase): + """A synchronous queue for use in conjunction with the :class:`SynchronousSender`. The queue will call + :func:`send` on :func:`sender` when it reaches :func:`max_queue_length`, or when the consumer calls + :func:`flush`. + + .. code:: python + + from application_insights.channel import SynchronousQueue + queue = SynchronousQueue(None) + queue.max_queue_length = 1 + queue.put(1) + """ + def __init__(self, sender): + """Initializes a new instance of the class. + + Args: + sender (:class:`SenderBase`) the sender object that will be used in conjunction with this queue. + """ + QueueBase.__init__(self, sender) + + def flush(self): + """Flushes the current queue by by calling :func:`sender`'s :func:`send` method. + """ + local_sender = self.sender + if not local_sender: + return + while True: + # get at most send_buffer_size items and send them + data = [] + while len(data) < local_sender.send_buffer_size: + item = self.get() + if not item: + break + data.append(item) + if len(data) == 0: + break + local_sender.send(data) diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousQueue.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousQueue.pyc new file mode 100644 index 0000000..965addb Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousQueue.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousSender.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousSender.py new file mode 100644 index 0000000..b9fcebe --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousSender.py @@ -0,0 +1,13 @@ +from .SenderBase import SenderBase + +class SynchronousSender(SenderBase): + """A synchronous sender that works in conjunction with the :class:`SynchronousQueue`. The queue will call + :func:`send` on the current instance with the data to send. + """ + def __init__(self, service_endpoint_uri='https://dc.services.visualstudio.com/v2/track'): + """Initializes a new instance of the class. + + Args: + sender (String) service_endpoint_uri the address of the service to send telemetry data to. + """ + SenderBase.__init__(self, service_endpoint_uri) \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousSender.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousSender.pyc new file mode 100644 index 0000000..bd19036 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/SynchronousSender.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryChannel.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryChannel.py new file mode 100644 index 0000000..b193344 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryChannel.py @@ -0,0 +1,122 @@ +import datetime +import sys + +from .SynchronousQueue import SynchronousQueue +from .SynchronousSender import SynchronousSender +from .TelemetryContext import TelemetryContext +from applicationinsights.channel import contracts + +platform_moniker = 'py2' +if sys.version_info >= (3, 0): + platform_moniker = 'py3' + +# set up internal context +internal_context = contracts.Internal() +internal_context.sdk_version = platform_moniker + ':0.10.0' + +class TelemetryChannel(object): + """The telemetry channel is responsible for constructing a :class:`contracts.Envelope` object from the passed in + data and specified telemetry context. + + .. code:: python + + from application_insights.channel import TelemetryChannel, contracts + channel = TelemetryChannel() + event = contracts.EventData() + event.name = 'My event' + channel.write(event) + """ + def __init__(self, context=None, queue=None): + """Initializes a new instance of the class. + + Args: + context (:class:`TelemetryContext') the telemetry context to use when sending telemetry data.\n + queue (:class:`QueueBase`) the queue to enqueue the resulting :class:`contracts.Envelope` to. + """ + self._context = context or TelemetryContext() + self._queue = queue or SynchronousQueue(SynchronousSender()) + + @property + def context(self): + """The context associated with this channel. All :class:`contracts.Envelope` objects created by this channel + will use this value if it's present or if none is specified as part of the :func:`write` call. + + Returns: + (:class:`TelemetryContext`). the context instance (defaults to: TelemetryContext()) + """ + return self._context + + @property + def queue(self): + """The queue associated with this channel. All :class:`contracts.Envelope` objects created by this channel + will be pushed to this queue. + + Returns: + (:class:`QueueBase`). the queue instance (defaults to: SynchronousQueue()) + """ + return self._queue + + @property + def sender(self): + """The sender associated with this channel. This instance will be used to transmit telemetry to the service. + + Returns: + (:class:`SenderBase`). the sender instance (defaults to: SynchronousSender()) + """ + return self._queue.sender + + def flush(self): + """Flushes the enqueued data by calling :func:`flush` on :func:`queue`. + """ + self._queue.flush() + + def write(self, data, context=None): + """Enqueues the passed in data to the :func:`queue`. If the caller specifies a context as well, it will + take precedence over the instance in :func:`context`. + + Args: + data (object). data the telemetry data to send. This will be wrapped in an :class:`contracts.Envelope` + before being enqueued to the :func:`queue`. + context (:class:`TelemetryContext`). context the override context to use when constructing the + :class:`contracts.Envelope`. + """ + local_context = context or self._context + if not local_context: + raise Exception('Context was required but not provided') + + if not data: + raise Exception('Data was required but not provided') + + envelope = contracts.Envelope() + envelope.name = data.ENVELOPE_TYPE_NAME + envelope.time = datetime.datetime.utcnow().isoformat() + 'Z' + envelope.ikey = local_context.instrumentation_key + tags = envelope.tags + for key, value in self._write_tags(local_context): + tags[key] = value + envelope.data = contracts.Data() + envelope.data.base_type = data.DATA_TYPE_NAME + if hasattr(data, 'properties') and local_context.properties: + properties = data.properties + if not properties: + properties = {} + data.properties = properties + for key, value in local_context.properties: + if key not in properties: + properties[key] = value + envelope.data.base_data = data + + self._queue.put(envelope) + + def _write_tags(self, context): + for item in [ internal_context, context.device, context.application, context.user, context.session, context.location, context.operation ]: + if not item: + continue + for pair in item.write().items(): + yield pair + + + + + + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryChannel.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryChannel.pyc new file mode 100644 index 0000000..c9b7dfc Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryChannel.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryContext.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryContext.py new file mode 100644 index 0000000..bcb4b4c --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryContext.py @@ -0,0 +1,54 @@ +import platform +import locale + +from applicationinsights.channel import contracts + +# save off whatever is currently there +existing_device_initialize = contracts.Device._initialize +def device_initialize(self): + """ The device initializer used to assign special properties to all device context objects""" + existing_device_initialize(self) + self.type = 'Other' + self.id = platform.node() + self.os_version = platform.version() + self.locale = locale.getdefaultlocale()[0] + +# assign the device context initializer +contracts.Device._initialize = device_initialize + +class TelemetryContext(object): + """Represents the context for sending telemetry to the Application Insights service. + + .. code:: python + + context = TelemetryContext() + context.instrumentation_key = '' + context.application.id = 'My application' + context.application.ver = '1.2.3' + context.device.id = 'My current device' + context.device.oem_name = 'Asus' + context.device.model = 'X31A' + context.device.type = "Other" + context.user.id = 'santa@northpole.net' + track_trace('My trace with context') + """ + def __init__(self): + """Initializes a new instance of the class. + """ + self.instrumentation_key = None + self.device = contracts.Device() + self.application = contracts.Application() + self.user = contracts.User() + self.session = contracts.Session() + self.operation = contracts.Operation() + self.location = contracts.Location() + self._properties = {} + + @property + def properties(self): + """The property context. This contains free-form properties that you can add to your telemetry. + + Returns: + (dict). the context object. + """ + return self._properties diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryContext.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryContext.pyc new file mode 100644 index 0000000..13bcaf8 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/TelemetryContext.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/__init__.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/__init__.py new file mode 100644 index 0000000..9aaf9ac --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/__init__.py @@ -0,0 +1,9 @@ +from .AsynchronousQueue import AsynchronousQueue +from .AsynchronousSender import AsynchronousSender +from .SenderBase import SenderBase +from .QueueBase import QueueBase +from .SynchronousQueue import SynchronousQueue +from .SynchronousSender import SynchronousSender +from .TelemetryChannel import TelemetryChannel +from .TelemetryContext import TelemetryContext +from . import contracts \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/__init__.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/__init__.pyc new file mode 100644 index 0000000..c9bcf34 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/__init__.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Application.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Application.py new file mode 100644 index 0000000..7db829d --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Application.py @@ -0,0 +1,54 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Application(object): + """Data contract class for type Application. + """ + _defaults = collections.OrderedDict([ + ('ai.application.ver', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.application.ver' in self._values: + return self._values['ai.application.ver'] + return self._defaults['ai.application.ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.application.ver'] and 'ai.application.ver' in self._values: + del self._values['ai.application.ver'] + else: + self._values['ai.application.ver'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Application.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Application.pyc new file mode 100644 index 0000000..fc8dc0e Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Application.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Data.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Data.py new file mode 100644 index 0000000..9ecbaf1 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Data.py @@ -0,0 +1,74 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Data(object): + """Data contract class for type Data. + """ + _defaults = collections.OrderedDict([ + ('baseType', None), + ('baseData', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'baseData': None + } + self._initialize() + + @property + def base_type(self): + """The base_type property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'baseType' in self._values: + return self._values['baseType'] + return self._defaults['baseType'] + + @base_type.setter + def base_type(self, value): + """The base_type property. + + Args: + value (string). the property value. + """ + if value == self._defaults['baseType'] and 'baseType' in self._values: + del self._values['baseType'] + else: + self._values['baseType'] = value + + @property + def base_data(self): + """The base_data property. + + Returns: + (object). the property value. (defaults to: None) + """ + return self._values['baseData'] + + @base_data.setter + def base_data(self, value): + """The base_data property. + + Args: + value (object). the property value. + """ + self._values['baseData'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Data.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Data.pyc new file mode 100644 index 0000000..f2d806d Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Data.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPoint.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPoint.py new file mode 100644 index 0000000..9212362 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPoint.py @@ -0,0 +1,192 @@ +import collections +import copy +from .Utils import _write_complex_object +from .DataPointType import DataPointType + +class DataPoint(object): + """Data contract class for type DataPoint. + """ + _defaults = collections.OrderedDict([ + ('name', None), + ('kind', DataPointType.measurement), + ('value', None), + ('count', None), + ('min', None), + ('max', None), + ('stdDev', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'name': None, + 'kind': DataPointType.measurement, + 'value': None, + } + self._initialize() + + @property + def name(self): + """The name property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['name'] + + @name.setter + def name(self, value): + """The name property. + + Args: + value (string). the property value. + """ + self._values['name'] = value + + @property + def kind(self): + """The kind property. + + Returns: + (:class:`DataPointType.measurement`). the property value. (defaults to: DataPointType.measurement) + """ + if 'kind' in self._values: + return self._values['kind'] + return self._defaults['kind'] + + @kind.setter + def kind(self, value): + """The kind property. + + Args: + value (:class:`DataPointType.measurement`). the property value. + """ + if value == self._defaults['kind'] and 'kind' in self._values: + del self._values['kind'] + else: + self._values['kind'] = value + + @property + def value(self): + """The value property. + + Returns: + (float). the property value. (defaults to: None) + """ + return self._values['value'] + + @value.setter + def value(self, value): + """The value property. + + Args: + value (float). the property value. + """ + self._values['value'] = value + + @property + def count(self): + """The count property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'count' in self._values: + return self._values['count'] + return self._defaults['count'] + + @count.setter + def count(self, value): + """The count property. + + Args: + value (int). the property value. + """ + if value == self._defaults['count'] and 'count' in self._values: + del self._values['count'] + else: + self._values['count'] = value + + @property + def min(self): + """The min property. + + Returns: + (float). the property value. (defaults to: None) + """ + if 'min' in self._values: + return self._values['min'] + return self._defaults['min'] + + @min.setter + def min(self, value): + """The min property. + + Args: + value (float). the property value. + """ + if value == self._defaults['min'] and 'min' in self._values: + del self._values['min'] + else: + self._values['min'] = value + + @property + def max(self): + """The max property. + + Returns: + (float). the property value. (defaults to: None) + """ + if 'max' in self._values: + return self._values['max'] + return self._defaults['max'] + + @max.setter + def max(self, value): + """The max property. + + Args: + value (float). the property value. + """ + if value == self._defaults['max'] and 'max' in self._values: + del self._values['max'] + else: + self._values['max'] = value + + @property + def std_dev(self): + """The std_dev property. + + Returns: + (float). the property value. (defaults to: None) + """ + if 'stdDev' in self._values: + return self._values['stdDev'] + return self._defaults['stdDev'] + + @std_dev.setter + def std_dev(self, value): + """The std_dev property. + + Args: + value (float). the property value. + """ + if value == self._defaults['stdDev'] and 'stdDev' in self._values: + del self._values['stdDev'] + else: + self._values['stdDev'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPoint.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPoint.pyc new file mode 100644 index 0000000..591b2d7 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPoint.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPointType.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPointType.py new file mode 100644 index 0000000..e0d95ae --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPointType.py @@ -0,0 +1,9 @@ +class DataPointType(object): + """Data contract class for type DataPointType.""" + # Enumeration value measurement + measurement = 0 + + # Enumeration value aggregation + aggregation = 1 + + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPointType.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPointType.pyc new file mode 100644 index 0000000..3c998bd Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DataPointType.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencyKind.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencyKind.py new file mode 100644 index 0000000..dd4400c --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencyKind.py @@ -0,0 +1,15 @@ +class DependencyKind(object): + """Data contract class for type DependencyKind.""" + # Enumeration value undefined + undefined = 0 + + # Enumeration value http_only + http_only = 1 + + # Enumeration value http_any + http_any = 2 + + # Enumeration value sql + sql = 3 + + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencyKind.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencyKind.pyc new file mode 100644 index 0000000..c4e60d6 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencyKind.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencySourceType.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencySourceType.py new file mode 100644 index 0000000..f90eefe --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencySourceType.py @@ -0,0 +1,12 @@ +class DependencySourceType(object): + """Data contract class for type DependencySourceType.""" + # Enumeration value undefined + undefined = 0 + + # Enumeration value aic + aic = 1 + + # Enumeration value apmc + apmc = 2 + + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencySourceType.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencySourceType.pyc new file mode 100644 index 0000000..3cc9bfd Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/DependencySourceType.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Device.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Device.py new file mode 100644 index 0000000..85c7a93 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Device.py @@ -0,0 +1,366 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Device(object): + """Data contract class for type Device. + """ + _defaults = collections.OrderedDict([ + ('ai.device.id', None), + ('ai.device.ip', None), + ('ai.device.language', None), + ('ai.device.locale', None), + ('ai.device.model', None), + ('ai.device.network', None), + ('ai.device.oemName', None), + ('ai.device.os', None), + ('ai.device.osVersion', None), + ('ai.device.roleInstance', None), + ('ai.device.roleName', None), + ('ai.device.screenResolution', None), + ('ai.device.type', None), + ('ai.device.vmName', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + } + self._initialize() + + @property + def id(self): + """The id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.id' in self._values: + return self._values['ai.device.id'] + return self._defaults['ai.device.id'] + + @id.setter + def id(self, value): + """The id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.id'] and 'ai.device.id' in self._values: + del self._values['ai.device.id'] + else: + self._values['ai.device.id'] = value + + @property + def ip(self): + """The ip property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.ip' in self._values: + return self._values['ai.device.ip'] + return self._defaults['ai.device.ip'] + + @ip.setter + def ip(self, value): + """The ip property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.ip'] and 'ai.device.ip' in self._values: + del self._values['ai.device.ip'] + else: + self._values['ai.device.ip'] = value + + @property + def language(self): + """The language property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.language' in self._values: + return self._values['ai.device.language'] + return self._defaults['ai.device.language'] + + @language.setter + def language(self, value): + """The language property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.language'] and 'ai.device.language' in self._values: + del self._values['ai.device.language'] + else: + self._values['ai.device.language'] = value + + @property + def locale(self): + """The locale property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.locale' in self._values: + return self._values['ai.device.locale'] + return self._defaults['ai.device.locale'] + + @locale.setter + def locale(self, value): + """The locale property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.locale'] and 'ai.device.locale' in self._values: + del self._values['ai.device.locale'] + else: + self._values['ai.device.locale'] = value + + @property + def model(self): + """The model property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.model' in self._values: + return self._values['ai.device.model'] + return self._defaults['ai.device.model'] + + @model.setter + def model(self, value): + """The model property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.model'] and 'ai.device.model' in self._values: + del self._values['ai.device.model'] + else: + self._values['ai.device.model'] = value + + @property + def network(self): + """The network property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.network' in self._values: + return self._values['ai.device.network'] + return self._defaults['ai.device.network'] + + @network.setter + def network(self, value): + """The network property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.network'] and 'ai.device.network' in self._values: + del self._values['ai.device.network'] + else: + self._values['ai.device.network'] = value + + @property + def oem_name(self): + """The oem_name property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.oemName' in self._values: + return self._values['ai.device.oemName'] + return self._defaults['ai.device.oemName'] + + @oem_name.setter + def oem_name(self, value): + """The oem_name property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.oemName'] and 'ai.device.oemName' in self._values: + del self._values['ai.device.oemName'] + else: + self._values['ai.device.oemName'] = value + + @property + def os(self): + """The os property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.os' in self._values: + return self._values['ai.device.os'] + return self._defaults['ai.device.os'] + + @os.setter + def os(self, value): + """The os property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.os'] and 'ai.device.os' in self._values: + del self._values['ai.device.os'] + else: + self._values['ai.device.os'] = value + + @property + def os_version(self): + """The os_version property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.osVersion' in self._values: + return self._values['ai.device.osVersion'] + return self._defaults['ai.device.osVersion'] + + @os_version.setter + def os_version(self, value): + """The os_version property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.osVersion'] and 'ai.device.osVersion' in self._values: + del self._values['ai.device.osVersion'] + else: + self._values['ai.device.osVersion'] = value + + @property + def role_instance(self): + """The role_instance property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.roleInstance' in self._values: + return self._values['ai.device.roleInstance'] + return self._defaults['ai.device.roleInstance'] + + @role_instance.setter + def role_instance(self, value): + """The role_instance property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.roleInstance'] and 'ai.device.roleInstance' in self._values: + del self._values['ai.device.roleInstance'] + else: + self._values['ai.device.roleInstance'] = value + + @property + def role_name(self): + """The role_name property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.roleName' in self._values: + return self._values['ai.device.roleName'] + return self._defaults['ai.device.roleName'] + + @role_name.setter + def role_name(self, value): + """The role_name property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.roleName'] and 'ai.device.roleName' in self._values: + del self._values['ai.device.roleName'] + else: + self._values['ai.device.roleName'] = value + + @property + def screen_resolution(self): + """The screen_resolution property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.screenResolution' in self._values: + return self._values['ai.device.screenResolution'] + return self._defaults['ai.device.screenResolution'] + + @screen_resolution.setter + def screen_resolution(self, value): + """The screen_resolution property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.screenResolution'] and 'ai.device.screenResolution' in self._values: + del self._values['ai.device.screenResolution'] + else: + self._values['ai.device.screenResolution'] = value + + @property + def type(self): + """The type property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.type' in self._values: + return self._values['ai.device.type'] + return self._defaults['ai.device.type'] + + @type.setter + def type(self, value): + """The type property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.type'] and 'ai.device.type' in self._values: + del self._values['ai.device.type'] + else: + self._values['ai.device.type'] = value + + @property + def vm_name(self): + """The vm_name property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.device.vmName' in self._values: + return self._values['ai.device.vmName'] + return self._defaults['ai.device.vmName'] + + @vm_name.setter + def vm_name(self, value): + """The vm_name property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.device.vmName'] and 'ai.device.vmName' in self._values: + del self._values['ai.device.vmName'] + else: + self._values['ai.device.vmName'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Device.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Device.pyc new file mode 100644 index 0000000..19794c2 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Device.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Envelope.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Envelope.py new file mode 100644 index 0000000..55ae4ee --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Envelope.py @@ -0,0 +1,385 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Envelope(object): + """Data contract class for type Envelope. + """ + _defaults = collections.OrderedDict([ + ('ver', 1), + ('name', None), + ('time', None), + ('sampleRate', 100.0), + ('seq', None), + ('iKey', None), + ('flags', None), + ('deviceId', None), + ('os', None), + ('osVer', None), + ('appId', None), + ('appVer', None), + ('userId', None), + ('tags', {}), + ('data', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 1, + 'name': None, + 'time': None, + 'sampleRate': 100.0, + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 1) + """ + if 'ver' in self._values: + return self._values['ver'] + return self._defaults['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + if value == self._defaults['ver'] and 'ver' in self._values: + del self._values['ver'] + else: + self._values['ver'] = value + + @property + def name(self): + """The name property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['name'] + + @name.setter + def name(self, value): + """The name property. + + Args: + value (string). the property value. + """ + self._values['name'] = value + + @property + def time(self): + """The time property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['time'] + + @time.setter + def time(self, value): + """The time property. + + Args: + value (string). the property value. + """ + self._values['time'] = value + + @property + def sample_rate(self): + """The sample_rate property. + + Returns: + (float). the property value. (defaults to: 100.0) + """ + if 'sampleRate' in self._values: + return self._values['sampleRate'] + return self._defaults['sampleRate'] + + @sample_rate.setter + def sample_rate(self, value): + """The sample_rate property. + + Args: + value (float). the property value. + """ + if value == self._defaults['sampleRate'] and 'sampleRate' in self._values: + del self._values['sampleRate'] + else: + self._values['sampleRate'] = value + + @property + def seq(self): + """The seq property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'seq' in self._values: + return self._values['seq'] + return self._defaults['seq'] + + @seq.setter + def seq(self, value): + """The seq property. + + Args: + value (string). the property value. + """ + if value == self._defaults['seq'] and 'seq' in self._values: + del self._values['seq'] + else: + self._values['seq'] = value + + @property + def ikey(self): + """The ikey property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'iKey' in self._values: + return self._values['iKey'] + return self._defaults['iKey'] + + @ikey.setter + def ikey(self, value): + """The ikey property. + + Args: + value (string). the property value. + """ + if value == self._defaults['iKey'] and 'iKey' in self._values: + del self._values['iKey'] + else: + self._values['iKey'] = value + + @property + def flags(self): + """The flags property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'flags' in self._values: + return self._values['flags'] + return self._defaults['flags'] + + @flags.setter + def flags(self, value): + """The flags property. + + Args: + value (int). the property value. + """ + if value == self._defaults['flags'] and 'flags' in self._values: + del self._values['flags'] + else: + self._values['flags'] = value + + @property + def device_id(self): + """The device_id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'deviceId' in self._values: + return self._values['deviceId'] + return self._defaults['deviceId'] + + @device_id.setter + def device_id(self, value): + """The device_id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['deviceId'] and 'deviceId' in self._values: + del self._values['deviceId'] + else: + self._values['deviceId'] = value + + @property + def os(self): + """The os property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'os' in self._values: + return self._values['os'] + return self._defaults['os'] + + @os.setter + def os(self, value): + """The os property. + + Args: + value (string). the property value. + """ + if value == self._defaults['os'] and 'os' in self._values: + del self._values['os'] + else: + self._values['os'] = value + + @property + def os_ver(self): + """The os_ver property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'osVer' in self._values: + return self._values['osVer'] + return self._defaults['osVer'] + + @os_ver.setter + def os_ver(self, value): + """The os_ver property. + + Args: + value (string). the property value. + """ + if value == self._defaults['osVer'] and 'osVer' in self._values: + del self._values['osVer'] + else: + self._values['osVer'] = value + + @property + def app_id(self): + """The app_id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'appId' in self._values: + return self._values['appId'] + return self._defaults['appId'] + + @app_id.setter + def app_id(self, value): + """The app_id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['appId'] and 'appId' in self._values: + del self._values['appId'] + else: + self._values['appId'] = value + + @property + def app_ver(self): + """The app_ver property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'appVer' in self._values: + return self._values['appVer'] + return self._defaults['appVer'] + + @app_ver.setter + def app_ver(self, value): + """The app_ver property. + + Args: + value (string). the property value. + """ + if value == self._defaults['appVer'] and 'appVer' in self._values: + del self._values['appVer'] + else: + self._values['appVer'] = value + + @property + def user_id(self): + """The user_id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'userId' in self._values: + return self._values['userId'] + return self._defaults['userId'] + + @user_id.setter + def user_id(self, value): + """The user_id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['userId'] and 'userId' in self._values: + del self._values['userId'] + else: + self._values['userId'] = value + + @property + def tags(self): + """The tags property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'tags' in self._values: + return self._values['tags'] + self._values['tags'] = copy.deepcopy(self._defaults['tags']) + return self._values['tags'] + + @tags.setter + def tags(self, value): + """The tags property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['tags'] and 'tags' in self._values: + del self._values['tags'] + else: + self._values['tags'] = value + + @property + def data(self): + """The data property. + + Returns: + (object). the property value. (defaults to: None) + """ + if 'data' in self._values: + return self._values['data'] + return self._defaults['data'] + + @data.setter + def data(self, value): + """The data property. + + Args: + value (object). the property value. + """ + if value == self._defaults['data'] and 'data' in self._values: + del self._values['data'] + else: + self._values['data'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Envelope.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Envelope.pyc new file mode 100644 index 0000000..718de09 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Envelope.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/EventData.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/EventData.py new file mode 100644 index 0000000..ed8c368 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/EventData.py @@ -0,0 +1,124 @@ +import collections +import copy +from .Utils import _write_complex_object + +class EventData(object): + """Data contract class for type EventData. + """ + ENVELOPE_TYPE_NAME = 'Microsoft.ApplicationInsights.Event' + + DATA_TYPE_NAME = 'EventData' + + _defaults = collections.OrderedDict([ + ('ver', 2), + ('name', None), + ('properties', {}), + ('measurements', {}) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 2, + 'name': None, + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 2) + """ + return self._values['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + self._values['ver'] = value + + @property + def name(self): + """The name property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['name'] + + @name.setter + def name(self, value): + """The name property. + + Args: + value (string). the property value. + """ + self._values['name'] = value + + @property + def properties(self): + """The properties property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'properties' in self._values: + return self._values['properties'] + self._values['properties'] = copy.deepcopy(self._defaults['properties']) + return self._values['properties'] + + @properties.setter + def properties(self, value): + """The properties property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['properties'] and 'properties' in self._values: + del self._values['properties'] + else: + self._values['properties'] = value + + @property + def measurements(self): + """The measurements property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'measurements' in self._values: + return self._values['measurements'] + self._values['measurements'] = copy.deepcopy(self._defaults['measurements']) + return self._values['measurements'] + + @measurements.setter + def measurements(self, value): + """The measurements property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['measurements'] and 'measurements' in self._values: + del self._values['measurements'] + else: + self._values['measurements'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/EventData.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/EventData.pyc new file mode 100644 index 0000000..0b6d67c Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/EventData.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionData.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionData.py new file mode 100644 index 0000000..ce3d76b --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionData.py @@ -0,0 +1,168 @@ +import collections +import copy +from .Utils import _write_complex_object + +class ExceptionData(object): + """Data contract class for type ExceptionData. + """ + ENVELOPE_TYPE_NAME = 'Microsoft.ApplicationInsights.Exception' + + DATA_TYPE_NAME = 'ExceptionData' + + _defaults = collections.OrderedDict([ + ('ver', 2), + ('handledAt', None), + ('exceptions', []), + ('severityLevel', None), + ('properties', {}), + ('measurements', {}) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 2, + 'handledAt': None, + 'exceptions': [], + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 2) + """ + return self._values['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + self._values['ver'] = value + + @property + def handled_at(self): + """The handled_at property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['handledAt'] + + @handled_at.setter + def handled_at(self, value): + """The handled_at property. + + Args: + value (string). the property value. + """ + self._values['handledAt'] = value + + @property + def exceptions(self): + """The exceptions property. + + Returns: + (list). the property value. (defaults to: []) + """ + return self._values['exceptions'] + + @exceptions.setter + def exceptions(self, value): + """The exceptions property. + + Args: + value (list). the property value. + """ + self._values['exceptions'] = value + + @property + def severity_level(self): + """The severity_level property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'severityLevel' in self._values: + return self._values['severityLevel'] + return self._defaults['severityLevel'] + + @severity_level.setter + def severity_level(self, value): + """The severity_level property. + + Args: + value (int). the property value. + """ + if value == self._defaults['severityLevel'] and 'severityLevel' in self._values: + del self._values['severityLevel'] + else: + self._values['severityLevel'] = value + + @property + def properties(self): + """The properties property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'properties' in self._values: + return self._values['properties'] + self._values['properties'] = copy.deepcopy(self._defaults['properties']) + return self._values['properties'] + + @properties.setter + def properties(self, value): + """The properties property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['properties'] and 'properties' in self._values: + del self._values['properties'] + else: + self._values['properties'] = value + + @property + def measurements(self): + """The measurements property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'measurements' in self._values: + return self._values['measurements'] + self._values['measurements'] = copy.deepcopy(self._defaults['measurements']) + return self._values['measurements'] + + @measurements.setter + def measurements(self, value): + """The measurements property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['measurements'] and 'measurements' in self._values: + del self._values['measurements'] + else: + self._values['measurements'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionData.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionData.pyc new file mode 100644 index 0000000..bac5011 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionData.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionDetails.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionDetails.py new file mode 100644 index 0000000..57b4eae --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionDetails.py @@ -0,0 +1,192 @@ +import collections +import copy +from .Utils import _write_complex_object + +class ExceptionDetails(object): + """Data contract class for type ExceptionDetails. + """ + _defaults = collections.OrderedDict([ + ('id', None), + ('outerId', None), + ('typeName', None), + ('message', None), + ('hasFullStack', True), + ('stack', None), + ('parsedStack', []) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'typeName': None, + 'message': None, + 'hasFullStack': True, + } + self._initialize() + + @property + def id(self): + """The id property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'id' in self._values: + return self._values['id'] + return self._defaults['id'] + + @id.setter + def id(self, value): + """The id property. + + Args: + value (int). the property value. + """ + if value == self._defaults['id'] and 'id' in self._values: + del self._values['id'] + else: + self._values['id'] = value + + @property + def outer_id(self): + """The outer_id property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'outerId' in self._values: + return self._values['outerId'] + return self._defaults['outerId'] + + @outer_id.setter + def outer_id(self, value): + """The outer_id property. + + Args: + value (int). the property value. + """ + if value == self._defaults['outerId'] and 'outerId' in self._values: + del self._values['outerId'] + else: + self._values['outerId'] = value + + @property + def type_name(self): + """The type_name property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['typeName'] + + @type_name.setter + def type_name(self, value): + """The type_name property. + + Args: + value (string). the property value. + """ + self._values['typeName'] = value + + @property + def message(self): + """The message property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['message'] + + @message.setter + def message(self, value): + """The message property. + + Args: + value (string). the property value. + """ + self._values['message'] = value + + @property + def has_full_stack(self): + """The has_full_stack property. + + Returns: + (bool). the property value. (defaults to: True) + """ + if 'hasFullStack' in self._values: + return self._values['hasFullStack'] + return self._defaults['hasFullStack'] + + @has_full_stack.setter + def has_full_stack(self, value): + """The has_full_stack property. + + Args: + value (bool). the property value. + """ + if value == self._defaults['hasFullStack'] and 'hasFullStack' in self._values: + del self._values['hasFullStack'] + else: + self._values['hasFullStack'] = value + + @property + def stack(self): + """The stack property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'stack' in self._values: + return self._values['stack'] + return self._defaults['stack'] + + @stack.setter + def stack(self, value): + """The stack property. + + Args: + value (string). the property value. + """ + if value == self._defaults['stack'] and 'stack' in self._values: + del self._values['stack'] + else: + self._values['stack'] = value + + @property + def parsed_stack(self): + """The parsed_stack property. + + Returns: + (list). the property value. (defaults to: []) + """ + if 'parsedStack' in self._values: + return self._values['parsedStack'] + self._values['parsedStack'] = copy.deepcopy(self._defaults['parsedStack']) + return self._values['parsedStack'] + + @parsed_stack.setter + def parsed_stack(self, value): + """The parsed_stack property. + + Args: + value (list). the property value. + """ + if value == self._defaults['parsedStack'] and 'parsedStack' in self._values: + del self._values['parsedStack'] + else: + self._values['parsedStack'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionDetails.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionDetails.pyc new file mode 100644 index 0000000..074434b Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/ExceptionDetails.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Internal.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Internal.py new file mode 100644 index 0000000..6138274 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Internal.py @@ -0,0 +1,78 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Internal(object): + """Data contract class for type Internal. + """ + _defaults = collections.OrderedDict([ + ('ai.internal.sdkVersion', None), + ('ai.internal.agentVersion', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + } + self._initialize() + + @property + def sdk_version(self): + """The sdk_version property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.internal.sdkVersion' in self._values: + return self._values['ai.internal.sdkVersion'] + return self._defaults['ai.internal.sdkVersion'] + + @sdk_version.setter + def sdk_version(self, value): + """The sdk_version property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.internal.sdkVersion'] and 'ai.internal.sdkVersion' in self._values: + del self._values['ai.internal.sdkVersion'] + else: + self._values['ai.internal.sdkVersion'] = value + + @property + def agent_version(self): + """The agent_version property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.internal.agentVersion' in self._values: + return self._values['ai.internal.agentVersion'] + return self._defaults['ai.internal.agentVersion'] + + @agent_version.setter + def agent_version(self, value): + """The agent_version property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.internal.agentVersion'] and 'ai.internal.agentVersion' in self._values: + del self._values['ai.internal.agentVersion'] + else: + self._values['ai.internal.agentVersion'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Internal.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Internal.pyc new file mode 100644 index 0000000..5dd5d8d Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Internal.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Location.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Location.py new file mode 100644 index 0000000..a6cfba5 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Location.py @@ -0,0 +1,54 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Location(object): + """Data contract class for type Location. + """ + _defaults = collections.OrderedDict([ + ('ai.location.ip', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + } + self._initialize() + + @property + def ip(self): + """The ip property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.location.ip' in self._values: + return self._values['ai.location.ip'] + return self._defaults['ai.location.ip'] + + @ip.setter + def ip(self, value): + """The ip property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.location.ip'] and 'ai.location.ip' in self._values: + del self._values['ai.location.ip'] + else: + self._values['ai.location.ip'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Location.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Location.pyc new file mode 100644 index 0000000..a833b18 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Location.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MessageData.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MessageData.py new file mode 100644 index 0000000..17cd4c7 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MessageData.py @@ -0,0 +1,123 @@ +import collections +import copy +from .Utils import _write_complex_object + +class MessageData(object): + """Data contract class for type MessageData. + """ + ENVELOPE_TYPE_NAME = 'Microsoft.ApplicationInsights.Message' + + DATA_TYPE_NAME = 'MessageData' + + _defaults = collections.OrderedDict([ + ('ver', 2), + ('message', None), + ('severityLevel', None), + ('properties', {}) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 2, + 'message': None, + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 2) + """ + return self._values['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + self._values['ver'] = value + + @property + def message(self): + """The message property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['message'] + + @message.setter + def message(self, value): + """The message property. + + Args: + value (string). the property value. + """ + self._values['message'] = value + + @property + def severity_level(self): + """The severity_level property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'severityLevel' in self._values: + return self._values['severityLevel'] + return self._defaults['severityLevel'] + + @severity_level.setter + def severity_level(self, value): + """The severity_level property. + + Args: + value (int). the property value. + """ + if value == self._defaults['severityLevel'] and 'severityLevel' in self._values: + del self._values['severityLevel'] + else: + self._values['severityLevel'] = value + + @property + def properties(self): + """The properties property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'properties' in self._values: + return self._values['properties'] + self._values['properties'] = copy.deepcopy(self._defaults['properties']) + return self._values['properties'] + + @properties.setter + def properties(self, value): + """The properties property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['properties'] and 'properties' in self._values: + del self._values['properties'] + else: + self._values['properties'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MessageData.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MessageData.pyc new file mode 100644 index 0000000..5c5177f Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MessageData.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MetricData.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MetricData.py new file mode 100644 index 0000000..d6a5088 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MetricData.py @@ -0,0 +1,99 @@ +import collections +import copy +from .Utils import _write_complex_object + +class MetricData(object): + """Data contract class for type MetricData. + """ + ENVELOPE_TYPE_NAME = 'Microsoft.ApplicationInsights.Metric' + + DATA_TYPE_NAME = 'MetricData' + + _defaults = collections.OrderedDict([ + ('ver', 2), + ('metrics', []), + ('properties', {}) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 2, + 'metrics': [], + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 2) + """ + return self._values['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + self._values['ver'] = value + + @property + def metrics(self): + """The metrics property. + + Returns: + (list). the property value. (defaults to: []) + """ + return self._values['metrics'] + + @metrics.setter + def metrics(self, value): + """The metrics property. + + Args: + value (list). the property value. + """ + self._values['metrics'] = value + + @property + def properties(self): + """The properties property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'properties' in self._values: + return self._values['properties'] + self._values['properties'] = copy.deepcopy(self._defaults['properties']) + return self._values['properties'] + + @properties.setter + def properties(self, value): + """The properties property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['properties'] and 'properties' in self._values: + del self._values['properties'] + else: + self._values['properties'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MetricData.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MetricData.pyc new file mode 100644 index 0000000..9946897 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/MetricData.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Operation.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Operation.py new file mode 100644 index 0000000..4c29736 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Operation.py @@ -0,0 +1,126 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Operation(object): + """Data contract class for type Operation. + """ + _defaults = collections.OrderedDict([ + ('ai.operation.id', None), + ('ai.operation.name', None), + ('ai.operation.parentId', None), + ('ai.operation.rootId', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + } + self._initialize() + + @property + def id(self): + """The id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.operation.id' in self._values: + return self._values['ai.operation.id'] + return self._defaults['ai.operation.id'] + + @id.setter + def id(self, value): + """The id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.operation.id'] and 'ai.operation.id' in self._values: + del self._values['ai.operation.id'] + else: + self._values['ai.operation.id'] = value + + @property + def name(self): + """The name property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.operation.name' in self._values: + return self._values['ai.operation.name'] + return self._defaults['ai.operation.name'] + + @name.setter + def name(self, value): + """The name property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.operation.name'] and 'ai.operation.name' in self._values: + del self._values['ai.operation.name'] + else: + self._values['ai.operation.name'] = value + + @property + def parent_id(self): + """The parent_id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.operation.parentId' in self._values: + return self._values['ai.operation.parentId'] + return self._defaults['ai.operation.parentId'] + + @parent_id.setter + def parent_id(self, value): + """The parent_id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.operation.parentId'] and 'ai.operation.parentId' in self._values: + del self._values['ai.operation.parentId'] + else: + self._values['ai.operation.parentId'] = value + + @property + def root_id(self): + """The root_id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.operation.rootId' in self._values: + return self._values['ai.operation.rootId'] + return self._defaults['ai.operation.rootId'] + + @root_id.setter + def root_id(self, value): + """The root_id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.operation.rootId'] and 'ai.operation.rootId' in self._values: + del self._values['ai.operation.rootId'] + else: + self._values['ai.operation.rootId'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Operation.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Operation.pyc new file mode 100644 index 0000000..1c9ef35 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Operation.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/PageViewData.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/PageViewData.py new file mode 100644 index 0000000..abd0e37 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/PageViewData.py @@ -0,0 +1,172 @@ +import collections +import copy +from .Utils import _write_complex_object + +class PageViewData(object): + """Data contract class for type PageViewData. + """ + ENVELOPE_TYPE_NAME = 'Microsoft.ApplicationInsights.PageView' + + DATA_TYPE_NAME = 'PageViewData' + + _defaults = collections.OrderedDict([ + ('ver', 2), + ('url', None), + ('name', None), + ('duration', None), + ('properties', {}), + ('measurements', {}) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 2, + 'name': None, + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 2) + """ + return self._values['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + self._values['ver'] = value + + @property + def url(self): + """The url property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'url' in self._values: + return self._values['url'] + return self._defaults['url'] + + @url.setter + def url(self, value): + """The url property. + + Args: + value (string). the property value. + """ + if value == self._defaults['url'] and 'url' in self._values: + del self._values['url'] + else: + self._values['url'] = value + + @property + def name(self): + """The name property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['name'] + + @name.setter + def name(self, value): + """The name property. + + Args: + value (string). the property value. + """ + self._values['name'] = value + + @property + def duration(self): + """The duration property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'duration' in self._values: + return self._values['duration'] + return self._defaults['duration'] + + @duration.setter + def duration(self, value): + """The duration property. + + Args: + value (string). the property value. + """ + if value == self._defaults['duration'] and 'duration' in self._values: + del self._values['duration'] + else: + self._values['duration'] = value + + @property + def properties(self): + """The properties property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'properties' in self._values: + return self._values['properties'] + self._values['properties'] = copy.deepcopy(self._defaults['properties']) + return self._values['properties'] + + @properties.setter + def properties(self, value): + """The properties property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['properties'] and 'properties' in self._values: + del self._values['properties'] + else: + self._values['properties'] = value + + @property + def measurements(self): + """The measurements property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'measurements' in self._values: + return self._values['measurements'] + self._values['measurements'] = copy.deepcopy(self._defaults['measurements']) + return self._values['measurements'] + + @measurements.setter + def measurements(self, value): + """The measurements property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['measurements'] and 'measurements' in self._values: + del self._values['measurements'] + else: + self._values['measurements'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/PageViewData.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/PageViewData.pyc new file mode 100644 index 0000000..d4c1a19 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/PageViewData.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RemoteDependencyData.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RemoteDependencyData.py new file mode 100644 index 0000000..7b438c9 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RemoteDependencyData.py @@ -0,0 +1,337 @@ +import collections +import copy +from .Utils import _write_complex_object +from .DataPointType import DataPointType +from .DependencyKind import DependencyKind +from .DependencySourceType import DependencySourceType + +class RemoteDependencyData(object): + """Data contract class for type RemoteDependencyData. + """ + ENVELOPE_TYPE_NAME = 'Microsoft.ApplicationInsights.RemoteDependency' + + DATA_TYPE_NAME = 'RemoteDependencyData' + + _defaults = collections.OrderedDict([ + ('ver', 2), + ('name', None), + ('kind', DataPointType.measurement), + ('value', None), + ('count', None), + ('min', None), + ('max', None), + ('stdDev', None), + ('dependencyKind', DependencyKind.undefined), + ('success', True), + ('async', None), + ('dependencySource', DependencySourceType.undefined), + ('properties', {}) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 2, + 'name': None, + 'kind': DataPointType.measurement, + 'value': None, + 'dependencyKind': DependencyKind.undefined, + 'success': True, + 'dependencySource': DependencySourceType.undefined, + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 2) + """ + return self._values['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + self._values['ver'] = value + + @property + def name(self): + """The name property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['name'] + + @name.setter + def name(self, value): + """The name property. + + Args: + value (string). the property value. + """ + self._values['name'] = value + + @property + def kind(self): + """The kind property. + + Returns: + (:class:`DataPointType.measurement`). the property value. (defaults to: DataPointType.measurement) + """ + if 'kind' in self._values: + return self._values['kind'] + return self._defaults['kind'] + + @kind.setter + def kind(self, value): + """The kind property. + + Args: + value (:class:`DataPointType.measurement`). the property value. + """ + if value == self._defaults['kind'] and 'kind' in self._values: + del self._values['kind'] + else: + self._values['kind'] = value + + @property + def value(self): + """The value property. + + Returns: + (float). the property value. (defaults to: None) + """ + return self._values['value'] + + @value.setter + def value(self, value): + """The value property. + + Args: + value (float). the property value. + """ + self._values['value'] = value + + @property + def count(self): + """The count property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'count' in self._values: + return self._values['count'] + return self._defaults['count'] + + @count.setter + def count(self, value): + """The count property. + + Args: + value (int). the property value. + """ + if value == self._defaults['count'] and 'count' in self._values: + del self._values['count'] + else: + self._values['count'] = value + + @property + def min(self): + """The min property. + + Returns: + (float). the property value. (defaults to: None) + """ + if 'min' in self._values: + return self._values['min'] + return self._defaults['min'] + + @min.setter + def min(self, value): + """The min property. + + Args: + value (float). the property value. + """ + if value == self._defaults['min'] and 'min' in self._values: + del self._values['min'] + else: + self._values['min'] = value + + @property + def max(self): + """The max property. + + Returns: + (float). the property value. (defaults to: None) + """ + if 'max' in self._values: + return self._values['max'] + return self._defaults['max'] + + @max.setter + def max(self, value): + """The max property. + + Args: + value (float). the property value. + """ + if value == self._defaults['max'] and 'max' in self._values: + del self._values['max'] + else: + self._values['max'] = value + + @property + def std_dev(self): + """The std_dev property. + + Returns: + (float). the property value. (defaults to: None) + """ + if 'stdDev' in self._values: + return self._values['stdDev'] + return self._defaults['stdDev'] + + @std_dev.setter + def std_dev(self, value): + """The std_dev property. + + Args: + value (float). the property value. + """ + if value == self._defaults['stdDev'] and 'stdDev' in self._values: + del self._values['stdDev'] + else: + self._values['stdDev'] = value + + @property + def dependency_kind(self): + """The dependency_kind property. + + Returns: + (:class:`DependencyKind.undefined`). the property value. (defaults to: DependencyKind.undefined) + """ + return self._values['dependencyKind'] + + @dependency_kind.setter + def dependency_kind(self, value): + """The dependency_kind property. + + Args: + value (:class:`DependencyKind.undefined`). the property value. + """ + self._values['dependencyKind'] = value + + @property + def success(self): + """The success property. + + Returns: + (bool). the property value. (defaults to: True) + """ + if 'success' in self._values: + return self._values['success'] + return self._defaults['success'] + + @success.setter + def success(self, value): + """The success property. + + Args: + value (bool). the property value. + """ + if value == self._defaults['success'] and 'success' in self._values: + del self._values['success'] + else: + self._values['success'] = value + + @property + def async(self): + """The async property. + + Returns: + (bool). the property value. (defaults to: None) + """ + if 'async' in self._values: + return self._values['async'] + return self._defaults['async'] + + @async.setter + def async(self, value): + """The async property. + + Args: + value (bool). the property value. + """ + if value == self._defaults['async'] and 'async' in self._values: + del self._values['async'] + else: + self._values['async'] = value + + @property + def dependency_source(self): + """The dependency_source property. + + Returns: + (:class:`DependencySourceType.undefined`). the property value. (defaults to: DependencySourceType.undefined) + """ + if 'dependencySource' in self._values: + return self._values['dependencySource'] + return self._defaults['dependencySource'] + + @dependency_source.setter + def dependency_source(self, value): + """The dependency_source property. + + Args: + value (:class:`DependencySourceType.undefined`). the property value. + """ + if value == self._defaults['dependencySource'] and 'dependencySource' in self._values: + del self._values['dependencySource'] + else: + self._values['dependencySource'] = value + + @property + def properties(self): + """The properties property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'properties' in self._values: + return self._values['properties'] + self._values['properties'] = copy.deepcopy(self._defaults['properties']) + return self._values['properties'] + + @properties.setter + def properties(self, value): + """The properties property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['properties'] and 'properties' in self._values: + del self._values['properties'] + else: + self._values['properties'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RemoteDependencyData.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RemoteDependencyData.pyc new file mode 100644 index 0000000..3d0f311 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RemoteDependencyData.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RequestData.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RequestData.py new file mode 100644 index 0000000..12cb263 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RequestData.py @@ -0,0 +1,276 @@ +import collections +import copy +from .Utils import _write_complex_object + +class RequestData(object): + """Data contract class for type RequestData. + """ + ENVELOPE_TYPE_NAME = 'Microsoft.ApplicationInsights.Request' + + DATA_TYPE_NAME = 'RequestData' + + _defaults = collections.OrderedDict([ + ('ver', 2), + ('id', None), + ('name', None), + ('startTime', None), + ('duration', None), + ('responseCode', None), + ('success', None), + ('httpMethod', None), + ('url', None), + ('properties', {}), + ('measurements', {}) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'ver': 2, + 'id': None, + 'startTime': None, + 'duration': None, + 'responseCode': None, + 'success': None, + } + self._initialize() + + @property + def ver(self): + """The ver property. + + Returns: + (int). the property value. (defaults to: 2) + """ + return self._values['ver'] + + @ver.setter + def ver(self, value): + """The ver property. + + Args: + value (int). the property value. + """ + self._values['ver'] = value + + @property + def id(self): + """The id property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['id'] + + @id.setter + def id(self, value): + """The id property. + + Args: + value (string). the property value. + """ + self._values['id'] = value + + @property + def name(self): + """The name property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'name' in self._values: + return self._values['name'] + return self._defaults['name'] + + @name.setter + def name(self, value): + """The name property. + + Args: + value (string). the property value. + """ + if value == self._defaults['name'] and 'name' in self._values: + del self._values['name'] + else: + self._values['name'] = value + + @property + def start_time(self): + """The start_time property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['startTime'] + + @start_time.setter + def start_time(self, value): + """The start_time property. + + Args: + value (string). the property value. + """ + self._values['startTime'] = value + + @property + def duration(self): + """The duration property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['duration'] + + @duration.setter + def duration(self, value): + """The duration property. + + Args: + value (string). the property value. + """ + self._values['duration'] = value + + @property + def response_code(self): + """The response_code property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['responseCode'] + + @response_code.setter + def response_code(self, value): + """The response_code property. + + Args: + value (string). the property value. + """ + self._values['responseCode'] = value + + @property + def success(self): + """The success property. + + Returns: + (bool). the property value. (defaults to: None) + """ + return self._values['success'] + + @success.setter + def success(self, value): + """The success property. + + Args: + value (bool). the property value. + """ + self._values['success'] = value + + @property + def http_method(self): + """The http_method property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'httpMethod' in self._values: + return self._values['httpMethod'] + return self._defaults['httpMethod'] + + @http_method.setter + def http_method(self, value): + """The http_method property. + + Args: + value (string). the property value. + """ + if value == self._defaults['httpMethod'] and 'httpMethod' in self._values: + del self._values['httpMethod'] + else: + self._values['httpMethod'] = value + + @property + def url(self): + """The url property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'url' in self._values: + return self._values['url'] + return self._defaults['url'] + + @url.setter + def url(self, value): + """The url property. + + Args: + value (string). the property value. + """ + if value == self._defaults['url'] and 'url' in self._values: + del self._values['url'] + else: + self._values['url'] = value + + @property + def properties(self): + """The properties property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'properties' in self._values: + return self._values['properties'] + self._values['properties'] = copy.deepcopy(self._defaults['properties']) + return self._values['properties'] + + @properties.setter + def properties(self, value): + """The properties property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['properties'] and 'properties' in self._values: + del self._values['properties'] + else: + self._values['properties'] = value + + @property + def measurements(self): + """The measurements property. + + Returns: + (hash). the property value. (defaults to: {}) + """ + if 'measurements' in self._values: + return self._values['measurements'] + self._values['measurements'] = copy.deepcopy(self._defaults['measurements']) + return self._values['measurements'] + + @measurements.setter + def measurements(self, value): + """The measurements property. + + Args: + value (hash). the property value. + """ + if value == self._defaults['measurements'] and 'measurements' in self._values: + del self._values['measurements'] + else: + self._values['measurements'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RequestData.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RequestData.pyc new file mode 100644 index 0000000..9f5a4e5 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/RequestData.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Session.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Session.py new file mode 100644 index 0000000..df63e34 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Session.py @@ -0,0 +1,102 @@ +import collections +import copy +from .Utils import _write_complex_object + +class Session(object): + """Data contract class for type Session. + """ + _defaults = collections.OrderedDict([ + ('ai.session.id', None), + ('ai.session.isFirst', None), + ('ai.session.isNew', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + } + self._initialize() + + @property + def id(self): + """The id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.session.id' in self._values: + return self._values['ai.session.id'] + return self._defaults['ai.session.id'] + + @id.setter + def id(self, value): + """The id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.session.id'] and 'ai.session.id' in self._values: + del self._values['ai.session.id'] + else: + self._values['ai.session.id'] = value + + @property + def is_first(self): + """The is_first property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.session.isFirst' in self._values: + return self._values['ai.session.isFirst'] + return self._defaults['ai.session.isFirst'] + + @is_first.setter + def is_first(self, value): + """The is_first property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.session.isFirst'] and 'ai.session.isFirst' in self._values: + del self._values['ai.session.isFirst'] + else: + self._values['ai.session.isFirst'] = value + + @property + def is_new(self): + """The is_new property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.session.isNew' in self._values: + return self._values['ai.session.isNew'] + return self._defaults['ai.session.isNew'] + + @is_new.setter + def is_new(self, value): + """The is_new property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.session.isNew'] and 'ai.session.isNew' in self._values: + del self._values['ai.session.isNew'] + else: + self._values['ai.session.isNew'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Session.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Session.pyc new file mode 100644 index 0000000..0718852 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Session.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/SeverityLevel.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/SeverityLevel.py new file mode 100644 index 0000000..be9a99a --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/SeverityLevel.py @@ -0,0 +1,18 @@ +class SeverityLevel(object): + """Data contract class for type 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 + + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/SeverityLevel.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/SeverityLevel.pyc new file mode 100644 index 0000000..d9371dc Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/SeverityLevel.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/StackFrame.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/StackFrame.py new file mode 100644 index 0000000..d7d834c --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/StackFrame.py @@ -0,0 +1,142 @@ +import collections +import copy +from .Utils import _write_complex_object + +class StackFrame(object): + """Data contract class for type StackFrame. + """ + _defaults = collections.OrderedDict([ + ('level', None), + ('method', None), + ('assembly', None), + ('fileName', None), + ('line', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + 'level': None, + 'method': None, + } + self._initialize() + + @property + def level(self): + """The level property. + + Returns: + (int). the property value. (defaults to: None) + """ + return self._values['level'] + + @level.setter + def level(self, value): + """The level property. + + Args: + value (int). the property value. + """ + self._values['level'] = value + + @property + def method(self): + """The method property. + + Returns: + (string). the property value. (defaults to: None) + """ + return self._values['method'] + + @method.setter + def method(self, value): + """The method property. + + Args: + value (string). the property value. + """ + self._values['method'] = value + + @property + def assembly(self): + """The assembly property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'assembly' in self._values: + return self._values['assembly'] + return self._defaults['assembly'] + + @assembly.setter + def assembly(self, value): + """The assembly property. + + Args: + value (string). the property value. + """ + if value == self._defaults['assembly'] and 'assembly' in self._values: + del self._values['assembly'] + else: + self._values['assembly'] = value + + @property + def file_name(self): + """The file_name property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'fileName' in self._values: + return self._values['fileName'] + return self._defaults['fileName'] + + @file_name.setter + def file_name(self, value): + """The file_name property. + + Args: + value (string). the property value. + """ + if value == self._defaults['fileName'] and 'fileName' in self._values: + del self._values['fileName'] + else: + self._values['fileName'] = value + + @property + def line(self): + """The line property. + + Returns: + (int). the property value. (defaults to: None) + """ + if 'line' in self._values: + return self._values['line'] + return self._defaults['line'] + + @line.setter + def line(self, value): + """The line property. + + Args: + value (int). the property value. + """ + if value == self._defaults['line'] and 'line' in self._values: + del self._values['line'] + else: + self._values['line'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/StackFrame.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/StackFrame.pyc new file mode 100644 index 0000000..e258576 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/StackFrame.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/User.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/User.py new file mode 100644 index 0000000..acf7a24 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/User.py @@ -0,0 +1,126 @@ +import collections +import copy +from .Utils import _write_complex_object + +class User(object): + """Data contract class for type User. + """ + _defaults = collections.OrderedDict([ + ('ai.user.accountAcquisitionDate', None), + ('ai.user.accountId', None), + ('ai.user.userAgent', None), + ('ai.user.id', None) + ]) + + def __init__(self): + """Initializes a new instance of the class. + """ + self._values = { + } + self._initialize() + + @property + def account_acquisition_date(self): + """The account_acquisition_date property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.user.accountAcquisitionDate' in self._values: + return self._values['ai.user.accountAcquisitionDate'] + return self._defaults['ai.user.accountAcquisitionDate'] + + @account_acquisition_date.setter + def account_acquisition_date(self, value): + """The account_acquisition_date property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.user.accountAcquisitionDate'] and 'ai.user.accountAcquisitionDate' in self._values: + del self._values['ai.user.accountAcquisitionDate'] + else: + self._values['ai.user.accountAcquisitionDate'] = value + + @property + def account_id(self): + """The account_id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.user.accountId' in self._values: + return self._values['ai.user.accountId'] + return self._defaults['ai.user.accountId'] + + @account_id.setter + def account_id(self, value): + """The account_id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.user.accountId'] and 'ai.user.accountId' in self._values: + del self._values['ai.user.accountId'] + else: + self._values['ai.user.accountId'] = value + + @property + def user_agent(self): + """The user_agent property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.user.userAgent' in self._values: + return self._values['ai.user.userAgent'] + return self._defaults['ai.user.userAgent'] + + @user_agent.setter + def user_agent(self, value): + """The user_agent property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.user.userAgent'] and 'ai.user.userAgent' in self._values: + del self._values['ai.user.userAgent'] + else: + self._values['ai.user.userAgent'] = value + + @property + def id(self): + """The id property. + + Returns: + (string). the property value. (defaults to: None) + """ + if 'ai.user.id' in self._values: + return self._values['ai.user.id'] + return self._defaults['ai.user.id'] + + @id.setter + def id(self, value): + """The id property. + + Args: + value (string). the property value. + """ + if value == self._defaults['ai.user.id'] and 'ai.user.id' in self._values: + del self._values['ai.user.id'] + else: + self._values['ai.user.id'] = value + + def _initialize(self): + """Initializes the current instance of the object. + """ + pass + + def write(self): + """Writes the contents of this object and returns the content as a dict object. + + Returns: + (dict). the object that represents the same data as the current instance. + """ + return _write_complex_object(self._defaults, self._values) + diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/User.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/User.pyc new file mode 100644 index 0000000..c570c74 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/User.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Utils.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Utils.py new file mode 100644 index 0000000..4c99d25 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Utils.py @@ -0,0 +1,44 @@ +import collections + +def _write_complex_object(defaults, values): + output = collections.OrderedDict() + for key in defaults.keys(): + default = defaults[key] + if key in values: + value = values[key] + if value == None: + value = default + elif default: + value = default + else: + continue + + if isinstance(value, list): + value_copy = [] + for item in value: + if hasattr(item, 'write') and callable(getattr(item, 'write')): + value_copy.append(item.write()) + else: + value_copy.append(item) + if len(value_copy) > 0: + output[key] = value_copy + elif isinstance(value, dict): + value_copy = collections.OrderedDict() + keys = sorted(value.keys()) + for item_key in keys: + item_value = value[item_key] + if hasattr(item_value, 'write') and callable(getattr(item_value, 'write')): + value_copy[item_key] = item_value.write() + else: + value_copy[item_key] = item_value + if len(value_copy) > 0: + output[key] = value_copy + elif hasattr(value, 'write') and callable(getattr(value, 'write')): + value_copy = value.write() + if len(value_copy) > 0: + output[key] = value_copy + else: + value_copy = value + output[key] = value_copy + + return output \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Utils.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Utils.pyc new file mode 100644 index 0000000..870d6bb Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/Utils.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/__init__.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/__init__.py new file mode 100644 index 0000000..adc59f5 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/__init__.py @@ -0,0 +1,23 @@ +from .Data import Data +from .Envelope import Envelope +from .DependencyKind import DependencyKind +from .SeverityLevel import SeverityLevel +from .DataPoint import DataPoint +from .MetricData import MetricData +from .RemoteDependencyData import RemoteDependencyData +from .RequestData import RequestData +from .StackFrame import StackFrame +from .ExceptionDetails import ExceptionDetails +from .ExceptionData import ExceptionData +from .MessageData import MessageData +from .EventData import EventData +from .PageViewData import PageViewData +from .DataPointType import DataPointType +from .DependencySourceType import DependencySourceType +from .Application import Application +from .Device import Device +from .Location import Location +from .Operation import Operation +from .Session import Session +from .User import User +from .Internal import Internal diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/__init__.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/__init__.pyc new file mode 100644 index 0000000..c312838 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/channel/contracts/__init__.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/exceptions/__init__.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/exceptions/__init__.py new file mode 100644 index 0000000..b30fceb --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/exceptions/__init__.py @@ -0,0 +1 @@ +from .enable import enable \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/exceptions/enable.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/exceptions/enable.py new file mode 100644 index 0000000..6488804 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/exceptions/enable.py @@ -0,0 +1,44 @@ +import sys +from applicationinsights import TelemetryClient, channel + +original_excepthook = None +telemetry_channel = None +enabled_instrumentation_keys = [] + +def enable(instrumentation_key, *args, **kwargs): + """Enables the automatic collection of unhandled exceptions. Captured exceptions will be sent to the Application + Insights service before being re-thrown. Multiple calls to this function with different instrumentation keys result + in multiple instances being submitted, one for each key. + + .. code:: python + + from applicationinsights.exceptions import enable + + # set up exception capture + enable('') + + # raise an exception (this will be sent to the Application Insights service as an exception telemetry object) + raise Exception('Boom!') + + Args: + instrumentation_key (str). the instrumentation key to use while sending telemetry to the service. + """ + if not instrumentation_key: + raise Exception('Instrumentation key was required but not provided') + global original_excepthook + global telemetry_channel + telemetry_channel = kwargs.get('telemetry_channel') + if not original_excepthook: + original_excepthook = sys.excepthook + sys.excepthook = intercept_excepthook + if instrumentation_key not in enabled_instrumentation_keys: + enabled_instrumentation_keys.append(instrumentation_key) + + +def intercept_excepthook(type, value, traceback): + client = TelemetryClient('temp_key', telemetry_channel) + for instrumentation_key in enabled_instrumentation_keys: + client.context.instrumentation_key = instrumentation_key + client.track_exception(type, value, traceback) + client.flush() + original_excepthook(type, value, traceback) \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/LoggingHandler.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/LoggingHandler.py new file mode 100644 index 0000000..a9b10b9 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/LoggingHandler.py @@ -0,0 +1,109 @@ +import logging +import applicationinsights + +enabled_instrumentation_keys = {} + +def enable(instrumentation_key, *args, **kwargs): + """Enables the Application Insights logging handler for the root logger for the supplied instrumentation key. + Multiple calls to this function with different instrumentation keys result in multiple handler instances. + + .. code:: python + + import logging + from applicationinsights.logging import enable + + # set up logging + enable('') + + # log something (this will be sent to the Application Insights service as a trace) + logging.info('This is a message') + + # logging shutdown will cause a flush of all un-sent telemetry items + # alternatively set up an async channel via enable('', telemetry_channel=...) + + Args: + instrumentation_key (str). the instrumentation key to use while sending telemetry to the service. + + Returns: + :class:`ApplicationInsightsHandler`. the newly created or existing handler. + """ + if not instrumentation_key: + raise Exception('Instrumentation key was required but not provided') + if instrumentation_key in enabled_instrumentation_keys: + logging.getLogger().removeHandler(enabled_instrumentation_keys[instrumentation_key]) + handler = LoggingHandler(instrumentation_key, *args, **kwargs) + handler.setLevel(logging.INFO) + enabled_instrumentation_keys[instrumentation_key] = handler + logging.getLogger().addHandler(handler) + return handler + + +class LoggingHandler(logging.Handler): + """This class represents an integration point between Python's logging framework and the Application Insights + service. + + Logging records are sent to the service either as simple Trace telemetry or as Exception telemetry (in the case + of exception information being available). + + .. code:: python + + import logging + from applicationinsights.logging import ApplicationInsightsHandler + + # set up logging + handler = ApplicationInsightsHandler('') + logging.basicConfig(handlers=[ handler ], format='%(levelname)s: %(message)s', level=logging.DEBUG) + + # log something (this will be sent to the Application Insights service as a trace) + logging.info('This is a message') + + # logging shutdown will cause a flush of all un-sent telemetry items + # alternatively flush manually via handler.flush() + """ + def __init__(self, instrumentation_key, *args, **kwargs): + """ + Initialize a new instance of the class. + + Args: + instrumentation_key (str). the instrumentation key to use while sending telemetry to the service. + """ + if not instrumentation_key: + raise Exception('Instrumentation key was required but not provided') + telemetry_channel = kwargs.get('telemetry_channel') + if 'telemetry_channel' in kwargs: + del kwargs['telemetry_channel'] + self.client = applicationinsights.TelemetryClient(instrumentation_key, telemetry_channel) + super(LoggingHandler, self).__init__(*args, **kwargs) + + def flush(self): + """Flushes the queued up telemetry to the service. + """ + self.client.flush() + return super(LoggingHandler, self).flush() + + def emit(self, record): + """Emit a record. + + If a formatter is specified, it is used to format the record. If exception information is present, an Exception + telemetry object is sent instead of a Trace telemetry object. + + Args: + record (:class:`logging.LogRecord`). the record to format and send. + """ + # the set of properties that will ride with the record + properties = { + 'process': record.processName, + 'module': record.module, + 'fileName': record.filename, + 'lineNumber': record.lineno, + 'level': record.levelname, + } + + # if we have exec_info, we will use it as an exception + if record.exc_info: + self.client.track_exception(*record.exc_info, properties=properties) + return + + # if we don't simply format the message and send the trace + formatted_message = self.format(record) + self.client.track_trace(formatted_message, properties=properties) diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/LoggingHandler.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/LoggingHandler.pyc new file mode 100644 index 0000000..2b65219 Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/LoggingHandler.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/__init__.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/__init__.py new file mode 100644 index 0000000..003329a --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/__init__.py @@ -0,0 +1,2 @@ +from .LoggingHandler import enable +from .LoggingHandler import LoggingHandler \ No newline at end of file diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/__init__.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/__init__.pyc new file mode 100644 index 0000000..69d71cf Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/logging/__init__.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/WSGIApplication.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/WSGIApplication.py new file mode 100644 index 0000000..acd42a7 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/WSGIApplication.py @@ -0,0 +1,97 @@ +import datetime +import re +import applicationinsights + +class WSGIApplication(object): + """ This class represents a WSGI wrapper that enables request telemetry for existing WSGI applications. The request + telemetry will be sent to Application Insights service using the supplied instrumentation key. + + .. code:: python + + from flask import Flask + from applicationinsights.requests import WSGIApplication + + # instantiate the Flask application and wrap its WSGI application + app = Flask(__name__) + app.wsgi_app = WSGIApplication('', app.wsgi_app) + + # define a simple route + @app.route('/') + def hello_world(): + return 'Hello World!' + + # run the application + if __name__ == '__main__': + app.run() + """ + def __init__(self, instrumentation_key, wsgi_application, *args, **kwargs): + """ + Initialize a new instance of the class. + + Args: + instrumentation_key (str). the instrumentation key to use while sending telemetry to the service.\n + wsgi_application (func). the WSGI application that we're wrapping. + """ + if not instrumentation_key: + raise Exception('Instrumentation key was required but not provided') + if not wsgi_application: + raise Exception('WSGI application was required but not provided') + telemetry_channel = kwargs.pop('telemetry_channel', None) + if not telemetry_channel: + sender = applicationinsights.channel.AsynchronousSender() + queue = applicationinsights.channel.AsynchronousQueue(sender) + telemetry_channel = applicationinsights.channel.TelemetryChannel(None, queue) + self.client = applicationinsights.TelemetryClient(instrumentation_key, telemetry_channel) + self._wsgi_application = wsgi_application + + def flush(self): + """Flushes the queued up telemetry to the service. + """ + self.client.flush() + + def __call__(self, environ, start_response): + """Callable implementation for WSGI middleware. + + Args: + environ (dict). a dictionary containing all WSGI environment properties for this request.\n + start_response (func). a function used to store the status, HTTP headers to be sent to the client and optional exception information. + + Returns: + (obj). the response to send back to the client. + """ + start_time = datetime.datetime.utcnow() + name = environ.get('PATH_INFO') or '/' + closure = {'status': '200 OK'} + + def status_interceptor(status_string, headers_array, exc_info=None): + closure['status'] = status_string + start_response(status_string, headers_array, exc_info) + + for part in self._wsgi_application(environ, status_interceptor): + yield part + + success = True + response_match = re.match(r'\s*(?P\d+)', closure['status']) + if response_match: + response_code = response_match.group('code') + if int(response_code) >= 400: + success = False + else: + response_code = closure['status'] + success = False + + http_method = environ.get('REQUEST_METHOD', 'GET') + url = name + query_string = environ.get('QUERY_STRING') + if query_string: + url += '?' + query_string + + scheme = environ.get('wsgi.url_scheme', 'http') + host = environ.get('HTTP_HOST', environ.get('SERVER_NAME', 'unknown')) + + url = scheme + '://' + host + url + + end_time = datetime.datetime.utcnow() + duration = int((end_time - start_time).total_seconds() * 1000) + + self.client.track_request(name, url, success, start_time.isoformat() + 'Z', duration, response_code, http_method) diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/WSGIApplication.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/WSGIApplication.pyc new file mode 100644 index 0000000..d347d3e Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/WSGIApplication.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/__init__.py b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/__init__.py new file mode 100644 index 0000000..e4b11d5 --- /dev/null +++ b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/__init__.py @@ -0,0 +1 @@ +from .WSGIApplication import WSGIApplication diff --git a/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/__init__.pyc b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/__init__.pyc new file mode 100644 index 0000000..5311a9c Binary files /dev/null and b/Ema.indigoPlugin/Contents/Server Plugin/applicationinsights/requests/__init__.pyc differ diff --git a/Ema.indigoPlugin/Contents/Server Plugin/plugin.py b/Ema.indigoPlugin/Contents/Server Plugin/plugin.py index 2920edd..58776c2 100644 --- a/Ema.indigoPlugin/Contents/Server Plugin/plugin.py +++ b/Ema.indigoPlugin/Contents/Server Plugin/plugin.py @@ -30,7 +30,7 @@ def __init__(self, pluginId, pluginDisplayName, pluginVersion, pluginPrefs): self.Password = None self.loginFailed = False - def _refreshStatesFromHardware(self, dev, logRefresh, commJustStarted): + def _refreshStatesFromHardware(self, dev): emaId = dev.pluginProps["emaId"] self.debugLog(u"Getting data for device: %s" % emaId) @@ -63,8 +63,10 @@ def startup(self): self.updater = GitHubPluginUpdater(self) self.updater.checkForUpdate() self.updateFrequency = float(self.pluginPrefs.get('updateFrequency', 24)) * 60.0 * 60.0 + self.refreshinterval = float(self.pluginPrefs.get('refreshinterval', 1)) * 60.0 * 60.0 self.debugLog(u"updateFrequency = " + str(self.updateFrequency)) self.next_update_check = time.time() + Ema.logTrace(self.Ema, "Startup", {'updateFrequency' : self.updateFrequency, 'refreshInterval': self.refreshinterval}) self.login(False) def login(self, force): @@ -93,10 +95,10 @@ def runConcurrentThread(self): if not dev.enabled: continue - self._refreshStatesFromHardware(dev, False, False) + self._refreshStatesFromHardware(dev) - self.debugLog("Sleep interval: %s" % self.updateFrequency) - self.sleep(self.updateFrequency) + self.debugLog("Sleep interval: %s" % self.refreshinterval) + self.sleep(self.refreshinterval) except self.StopThread: pass # Optionally catch the StopThread exception and do any needed cleanup. @@ -123,7 +125,6 @@ def deviceStartComm(self, dev): self.initDevice(dev) dev.stateListOrDisplayStateIdChanged() - #self._refreshStatesFromHardware(dev, True, True) def deviceStopComm(self, dev): # Called when communication with the hardware should be shutdown. @@ -170,6 +171,7 @@ def buildAvailableDeviceList(self): def showAvailableDevices(self): indigo.server.log("Number of devices found: %i" % (len(self.deviceList))) + Ema.logTrace(self.Ema, "showAvailableDevices", {'Number of devices' : (len(self.deviceList))}) for (id, details) in self.deviceList.iteritems(): indigo.server.log("\tSN:%s" % (details[0])) @@ -179,7 +181,7 @@ def deviceList1(self, filter, valuesDict, typeId, targetId): deviceListCopy = deepcopy(self.deviceList) for existingDevice in indigo.devices.iter("self"): for id in self.deviceList: - self.debugLog(" comparing %s against deviceList item %s" % (existingDevice.pluginProps["emaId"],id)) + self.debugLog("\tcomparing %s against deviceList item %s" % (existingDevice.pluginProps["emaId"],id)) if existingDevice.pluginProps["emaId"] == id: self.debugLog(" removing item %s" % (id)) del deviceListCopy[id]