def create_envelope(self, data_point, time_stamp, properties): envelope = Envelope( iKey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=time_stamp.isoformat(), ) envelope.name = "Microsoft.ApplicationInsights.Metric" data = MetricData(metrics=[data_point], properties=properties) envelope.data = Data(baseData=data, baseType="MetricData") return envelope
def _create_envelope(self, data_point, timestamp, properties): envelope = Envelope( iKey=self.options.instrumentation_key, tags=dict(utils.AZURE_MONITOR_CONTEXT), time=timestamp.isoformat(), ) envelope.name = "Microsoft.ApplicationInsights.Metric" data = MetricData(metrics=[data_point], properties=properties) envelope.data = Data(baseData=data, baseType="MetricData") return envelope
def test_apply(self): mixin = ProcessorMixin() mixin._telemetry_processors = [] def callback_function(envelope): envelope.baseType += '_world' mixin.add_telemetry_processor(callback_function) envelope = Envelope() envelope.baseType = 'type1' mixin.apply_telemetry_processors([envelope]) self.assertEqual(envelope.baseType, 'type1_world')
def test_apply_exception(self): mixin = ProcessorMixin() mixin._telemetry_processors = [] def callback_function(envelope): raise ValueError() def callback_function2(envelope): envelope.baseType += '_world2' mixin.add_telemetry_processor(callback_function) mixin.add_telemetry_processor(callback_function2) envelope = Envelope() envelope.baseType = 'type1' mixin.apply_telemetry_processors([envelope]) self.assertEqual(envelope.baseType, 'type1_world2')
def span_data_to_envelope(self, sd): envelope = Envelope( iKey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=sd.start_time, ) envelope.tags['ai.operation.id'] = sd.context.trace_id if sd.parent_span_id: envelope.tags['ai.operation.parentId'] = '|{}.{}.'.format( sd.context.trace_id, sd.parent_span_id, ) if sd.span_kind == SpanKind.SERVER: envelope.name = 'Microsoft.ApplicationInsights.Request' data = Request( id='|{}.{}.'.format(sd.context.trace_id, sd.span_id), duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), responseCode='0', # TODO success=True, # TODO ) envelope.data = Data(baseData=data, baseType='RequestData') if 'http.method' in sd.attributes: data.name = sd.attributes['http.method'] if 'http.url' in sd.attributes: data.name = data.name + ' ' + sd.attributes['http.url'] data.url = sd.attributes['http.url'] if 'http.status_code' in sd.attributes: data.responseCode = str(sd.attributes['http.status_code']) else: envelope.name = \ 'Microsoft.ApplicationInsights.RemoteDependency' data = RemoteDependency( name=sd.name, # TODO id='|{}.{}.'.format(sd.context.trace_id, sd.span_id), resultCode='0', # TODO duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), success=True, # TODO ) envelope.data = Data( baseData=data, baseType='RemoteDependencyData', ) if sd.span_kind == SpanKind.CLIENT: data.type = 'HTTP' # TODO if 'http.url' in sd.attributes: url = sd.attributes['http.url'] # TODO: error handling, probably put scheme as well data.name = utils.url_to_dependency_name(url) if 'http.status_code' in sd.attributes: data.resultCode = str(sd.attributes['http.status_code']) else: data.type = 'INPROC' # TODO: links, tracestate, tags, attrs return envelope
def log_record_to_envelope(self, record): envelope = Envelope( iKey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=utils.timestamp_to_iso_str(record.created), ) envelope.tags['ai.operation.id'] = getattr( record, 'traceId', '00000000000000000000000000000000', ) envelope.tags['ai.operation.parentId'] = '|{}.{}.'.format( envelope.tags['ai.operation.id'], getattr(record, 'spanId', '0000000000000000'), ) properties = { 'process': record.processName, 'module': record.module, 'fileName': record.pathname, 'lineNumber': record.lineno, 'level': record.levelname, } if record.exc_info: exctype, _value, tb = record.exc_info callstack = [] level = 0 for fileName, line, method, _text in traceback.extract_tb(tb): callstack.append({ 'level': level, 'method': method, 'fileName': fileName, 'line': line, }) level += 1 callstack.reverse() envelope.name = 'Microsoft.ApplicationInsights.Exception' data = ExceptionData( exceptions=[{ 'id': 1, 'outerId': 0, 'typeName': exctype.__name__, 'message': self.format(record), 'hasFullStack': True, 'parsedStack': callstack, }], severityLevel=max(0, record.levelno - 1) // 10, properties=properties, ) envelope.data = Data(baseData=data, baseType='ExceptionData') else: envelope.name = 'Microsoft.ApplicationInsights.Message' data = Message( message=self.format(record), severityLevel=max(0, record.levelno - 1) // 10, properties=properties, ) envelope.data = Data(baseData=data, baseType='MessageData') return envelope
def create_envelope(instrumentation_key, record): envelope = Envelope( iKey=instrumentation_key, tags=dict(utils.azure_monitor_context), time=utils.timestamp_to_iso_str(record.created), ) envelope.tags['ai.operation.id'] = getattr( record, 'traceId', '00000000000000000000000000000000', ) envelope.tags['ai.operation.parentId'] = '|{}.{}.'.format( envelope.tags['ai.operation.id'], getattr(record, 'spanId', '0000000000000000'), ) return envelope
def test_apply_not_accepted(self): mixin = ProcessorMixin() mixin._telemetry_processors = [] def callback_function(envelope): return envelope.baseType == 'type2' mixin.add_telemetry_processor(callback_function) envelope = Envelope() envelope.baseType = 'type1' envelope2 = Envelope() envelope2.baseType = 'type2' envelopes = mixin.apply_telemetry_processors([envelope, envelope2]) self.assertEqual(len(envelopes), 1) self.assertEqual(envelopes[0].baseType, 'type2')
def span_data_to_envelope(self, sd): envelope = Envelope( iKey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=sd.start_time, ) envelope.tags['ai.operation.id'] = sd.context.trace_id if sd.parent_span_id: envelope.tags['ai.operation.parentId'] = '{}'.format( sd.parent_span_id, ) if sd.span_kind == SpanKind.SERVER: envelope.name = 'Microsoft.ApplicationInsights.Request' data = Request( id='{}'.format(sd.span_id), duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), responseCode=str(sd.status.code), success=False, # Modify based off attributes or status properties={}, ) envelope.data = Data(baseData=data, baseType='RequestData') data.name = '' if 'http.method' in sd.attributes: data.name = sd.attributes['http.method'] if 'http.route' in sd.attributes: data.name = data.name + ' ' + sd.attributes['http.route'] envelope.tags['ai.operation.name'] = data.name data.properties['request.name'] = data.name elif 'http.path' in sd.attributes: data.properties['request.name'] = data.name + \ ' ' + sd.attributes['http.path'] if 'http.url' in sd.attributes: data.url = sd.attributes['http.url'] data.properties['request.url'] = sd.attributes['http.url'] if 'http.status_code' in sd.attributes: status_code = sd.attributes['http.status_code'] data.responseCode = str(status_code) data.success = ( status_code >= 200 and status_code <= 399 ) elif sd.status.code == 0: data.success = True else: envelope.name = \ 'Microsoft.ApplicationInsights.RemoteDependency' data = RemoteDependency( name=sd.name, # TODO id='{}'.format(sd.span_id), resultCode=str(sd.status.code), duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), success=False, # Modify based off attributes or status properties={}, ) envelope.data = Data( baseData=data, baseType='RemoteDependencyData', ) if sd.span_kind == SpanKind.CLIENT: data.type = sd.attributes.get('component') if 'http.url' in sd.attributes: url = sd.attributes['http.url'] # TODO: error handling, probably put scheme as well data.data = url parse_url = urlparse(url) # target matches authority (host:port) data.target = parse_url.netloc if 'http.method' in sd.attributes: # name is METHOD/path data.name = sd.attributes['http.method'] \ + ' ' + parse_url.path if 'http.status_code' in sd.attributes: status_code = sd.attributes["http.status_code"] data.resultCode = str(status_code) data.success = 200 <= status_code < 400 elif sd.status.code == 0: data.success = True else: data.type = 'INPROC' data.success = True if sd.links: links = [] for link in sd.links: links.append( {"operation_Id": link.trace_id, "id": link.span_id}) data.properties["_MS.links"] = json.dumps(links) # TODO: tracestate, tags for key in sd.attributes: # This removes redundant data from ApplicationInsights if key.startswith('http.'): continue data.properties[key] = sd.attributes[key] return envelope
def span_data_to_envelope(self, sd): envelope = Envelope( iKey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=sd.start_time, ) envelope.tags['ai.operation.id'] = sd.context.trace_id if sd.parent_span_id: envelope.tags['ai.operation.parentId'] = '{}'.format( sd.parent_span_id, ) if sd.span_kind == SpanKind.SERVER: if ERROR_MESSAGE in sd.attributes: envelope.name = 'Microsoft.ApplicationInsights.Exception' data = ExceptionData(exceptions=[{ 'id': 1, 'outerId': '{}'.format(sd.span_id), 'typeName': sd.attributes.get(ERROR_NAME, ''), 'message': sd.attributes[ERROR_MESSAGE], 'hasFullStack': STACKTRACE in sd.attributes, 'parsedStack': sd.attributes.get(STACKTRACE, None) }], ) envelope.data = Data(baseData=data, baseType='ExceptionData') yield envelope envelope.name = 'Microsoft.ApplicationInsights.Request' data = Request( id='{}'.format(sd.span_id), duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), responseCode=str(sd.status.code), success=False, # Modify based off attributes or status properties={}, ) envelope.data = Data(baseData=data, baseType='RequestData') data.name = '' if HTTP_METHOD in sd.attributes: data.name = sd.attributes[HTTP_METHOD] if HTTP_ROUTE in sd.attributes: data.name = data.name + ' ' + sd.attributes[HTTP_ROUTE] envelope.tags['ai.operation.name'] = data.name data.properties['request.name'] = data.name elif HTTP_PATH in sd.attributes: data.properties['request.name'] = data.name + \ ' ' + sd.attributes[HTTP_PATH] if HTTP_URL in sd.attributes: data.url = sd.attributes[HTTP_URL] data.properties['request.url'] = sd.attributes[HTTP_URL] if HTTP_STATUS_CODE in sd.attributes: status_code = sd.attributes[HTTP_STATUS_CODE] data.responseCode = str(status_code) data.success = (status_code >= 200 and status_code <= 399) elif sd.status.code == 0: data.success = True else: envelope.name = \ 'Microsoft.ApplicationInsights.RemoteDependency' data = RemoteDependency( name=sd.name, # TODO id='{}'.format(sd.span_id), resultCode=str(sd.status.code), duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), success=False, # Modify based off attributes or status properties={}, ) envelope.data = Data( baseData=data, baseType='RemoteDependencyData', ) if sd.span_kind == SpanKind.CLIENT: data.type = sd.attributes.get('component') if HTTP_URL in sd.attributes: url = sd.attributes[HTTP_URL] # TODO: error handling, probably put scheme as well data.data = url parse_url = urlparse(url) # target matches authority (host:port) data.target = parse_url.netloc if HTTP_METHOD in sd.attributes: # name is METHOD/path data.name = sd.attributes[HTTP_METHOD] \ + ' ' + parse_url.path if HTTP_STATUS_CODE in sd.attributes: status_code = sd.attributes[HTTP_STATUS_CODE] data.resultCode = str(status_code) data.success = 200 <= status_code < 400 elif sd.status.code == 0: data.success = True else: data.type = 'INPROC' data.success = True if sd.links: links = [] for link in sd.links: links.append({ "operation_Id": link.trace_id, "id": link.span_id }) data.properties["_MS.links"] = json.dumps(links) # TODO: tracestate, tags for key in sd.attributes: # This removes redundant data from ApplicationInsights if key.startswith('http.'): continue data.properties[key] = sd.attributes[key] yield envelope
def span_data_to_envelope(self, sd): envelope = Envelope( iKey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=sd.start_time, ) predefined_props = set() envelope.tags['ai.operation.id'] = sd.context.trace_id if sd.parent_span_id: envelope.tags['ai.operation.parentId'] = '{}'.format( sd.parent_span_id) if sd.span_kind == SpanKind.SERVER: envelope.name = 'Microsoft.ApplicationInsights.Request' data = Request( id='{}'.format(sd.span_id), duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), responseCode=str(sd.status.code), success=False, # Modify based off attributes or status properties={}, ) envelope.data = Data(baseData=data, baseType='RequestData') data.name = '' if 'http.method' in sd.attributes: data.name = sd.attributes['http.method'] if 'http.route' in sd.attributes: data.name = f"{data.name} {sd.attributes['http.route']}" envelope.tags['ai.operation.name'] = data.name data.properties['request.name'] = data.name elif 'http.path' in sd.attributes: data.properties[ 'request.name'] = f"{data.name} {sd.attributes['http.path']}" if 'http.url' in sd.attributes: data.url = sd.attributes['http.url'] data.properties['request.url'] = sd.attributes['http.url'] if 'http.status_code' in sd.attributes: status_code = sd.attributes['http.status_code'] data.responseCode = str(status_code) data.success = 200 <= status_code < 400 elif sd.status.code == 0: data.success = True else: envelope.name = 'Microsoft.ApplicationInsights.RemoteDependency' data = RemoteDependency( name=sd.name, # TODO id='{}'.format(sd.span_id), resultCode=str(sd.status.code), duration=utils.timestamp_to_duration( sd.start_time, sd.end_time, ), success=False, # Modify based off attributes or status properties={}, ) envelope.data = Data(baseData=data, baseType='RemoteDependencyData') if sd.span_kind == SpanKind.CLIENT: data.type = sd.attributes.get('component') if 'http.url' in sd.attributes: url = sd.attributes['http.url'] # TODO: error handling, probably put scheme as well data.data = url parse_url = urlparse(url) # target matches authority (host:port) data.target = parse_url.netloc if 'http.method' in sd.attributes: # name is METHOD/path data.name = f"{sd.attributes['http.method']} {parse_url.path}" if 'http.status_code' in sd.attributes: status_code = sd.attributes["http.status_code"] data.resultCode = str(status_code) data.success = 200 <= status_code < 400 elif sd.status.code == 0: data.success = True elif "dependency.type" in sd.attributes: data.type = sd.attributes.pop("dependency.type") for key in list(sd.attributes): if key == f"{data.type}.success": data.success = sd.attributes.pop(key) sd.attributes[ f"status_code"] = 200 if data.success else 500 data.resultCode = str(sd.attributes[f"status_code"]) predefined_props.add(key) continue elif key == f"{data.type}.target": data.target = sd.attributes.pop(key) predefined_props.add(key) continue elif key == f"{data.type}.data": data.data = sd.attributes.pop(key) predefined_props.add(key) continue if "error" in key: data.success = False trimmed_key = key.removeprefix(f"{data.type}.") data.properties[trimmed_key] = sd.attributes.get(key) predefined_props.add(key) # if f"{data.type}.query" in sd.attributes: # data.data = sd.attributes.pop(f"{data.type}.query") # if f"{data.type}.error" in sd.attributes: # data.success = False # data.properties["error"] = sd.attributes.pop(f"{data.type}.error") else: data.type = 'INPROC' data.success = True if sd.links: links = [] for link in sd.links: links.append({ "operation_Id": link.trace_id, "id": link.span_id }) data.properties["_MS.links"] = dumps(links) # TODO: tracestate, tags for key in sd.attributes: # This removes redundant data from ApplicationInsights if key.startswith('http.') or key in predefined_props: continue data.properties[key] = sd.attributes[key] return envelope